eve 0.84.1 → 0.85.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/src/channel/channel-operations.d.ts +2 -18
  3. package/dist/src/channel/compiled-channel.d.ts +3 -7
  4. package/dist/src/channel/cross-channel-receive.d.ts +9 -10
  5. package/dist/src/channel/cross-channel-receive.js +1 -1
  6. package/dist/src/channel/schedule.js +1 -1
  7. package/dist/src/channel/session.d.ts +26 -4
  8. package/dist/src/channel/session.js +1 -1
  9. package/dist/src/chunks/{use-eve-agent-DMeP0JOF.js → use-eve-agent-B2jCfcnG.js} +3 -2
  10. package/dist/src/chunks/{use-eve-agent-DP5Rso9C.js → use-eve-agent-DCLFi26P.js} +3 -2
  11. package/dist/src/client/client.js +1 -1
  12. package/dist/src/client/open-stream.js +1 -1
  13. package/dist/src/client/types.d.ts +5 -4
  14. package/dist/src/compiled/.vendor-stamp.json +1 -1
  15. package/dist/src/context/keys.d.ts +7 -0
  16. package/dist/src/context/keys.js +1 -1
  17. package/dist/src/execution/agent-sessions/context.d.ts +5 -1
  18. package/dist/src/execution/agent-sessions/context.js +1 -1
  19. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  20. package/dist/src/execution/legacy-session/snapshot.d.ts +1 -2
  21. package/dist/src/execution/legacy-session/snapshot.js +1 -1
  22. package/dist/src/execution/proxied-deliver-step.js +1 -1
  23. package/dist/src/execution/public-destination.d.ts +3 -0
  24. package/dist/src/execution/public-destination.js +1 -1
  25. package/dist/src/execution/publish-session-events.js +1 -1
  26. package/dist/src/execution/session/checkpoint-migrations.d.ts +16 -5
  27. package/dist/src/execution/session/checkpoint-migrations.js +1 -1
  28. package/dist/src/execution/session/checkpoint-refusal.d.ts +4 -0
  29. package/dist/src/execution/session/checkpoint-refusal.js +1 -0
  30. package/dist/src/execution/session/entry.js +1 -1
  31. package/dist/src/execution/session/handoff-steps.d.ts +7 -1
  32. package/dist/src/execution/session/handoff-steps.js +1 -1
  33. package/dist/src/execution/session/imported-conversation.d.ts +2 -0
  34. package/dist/src/execution/session/imported-conversation.js +1 -0
  35. package/dist/src/execution/session/interrupted-step.js +1 -1
  36. package/dist/src/execution/session/pre-v27-checkpoint.d.ts +36 -0
  37. package/dist/src/execution/session/pre-v27-checkpoint.js +1 -0
  38. package/dist/src/execution/session/program.d.ts +2 -0
  39. package/dist/src/execution/session/program.js +1 -1
  40. package/dist/src/execution/session/turn-step.js +1 -1
  41. package/dist/src/execution/session-callback-request.js +1 -1
  42. package/dist/src/execution/tool-auth.js +1 -1
  43. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  44. package/dist/src/execution/tools/channel-to.d.ts +12 -0
  45. package/dist/src/execution/tools/channel-to.js +1 -0
  46. package/dist/src/execution/tools/workflow/body.d.ts +3 -0
  47. package/dist/src/execution/tools/workflow/body.js +1 -1
  48. package/dist/src/execution/tools/workflow/step-context.d.ts +5 -0
  49. package/dist/src/execution/tools/workflow/step-execution.js +1 -1
  50. package/dist/src/execution/tools/workflow/step.js +1 -1
  51. package/dist/src/execution/workflow-callback-url.d.ts +2 -3
  52. package/dist/src/execution/workflow-callback-url.js +1 -1
  53. package/dist/src/execution/workflow-runtime.js +1 -1
  54. package/dist/src/harness/compaction/step.js +1 -1
  55. package/dist/src/harness/model-call/call.js +1 -1
  56. package/dist/src/harness/model-call/run.js +1 -1
  57. package/dist/src/harness/session-machine/transitions.js +1 -1
  58. package/dist/src/internal/application/stamped-package-version.js +1 -1
  59. package/dist/src/internal/attachments/limited-read.d.ts +2 -0
  60. package/dist/src/internal/attachments/limited-read.js +1 -1
  61. package/dist/src/internal/attachments/url-refs.js +1 -1
  62. package/dist/src/internal/capability-error.d.ts +3 -0
  63. package/dist/src/internal/capability-error.js +1 -0
  64. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +1 -1
  65. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  66. package/dist/src/public/channels/github/githubChannel.js +1 -1
  67. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  68. package/dist/src/public/channels/linq/inboundContent.js +1 -1
  69. package/dist/src/public/channels/slack/answers.d.ts +2 -3
  70. package/dist/src/public/channels/slack/answers.js +1 -1
  71. package/dist/src/public/channels/slack/api.d.ts +23 -3
  72. package/dist/src/public/channels/slack/api.js +1 -1
  73. package/dist/src/public/channels/slack/app-manifest.d.ts +2 -0
  74. package/dist/src/public/channels/slack/app-manifest.js +1 -1
  75. package/dist/src/public/channels/slack/auth.d.ts +2 -1
  76. package/dist/src/public/channels/slack/auth.js +1 -1
  77. package/dist/src/public/channels/slack/code-channel.d.ts +42 -0
  78. package/dist/src/public/channels/slack/code-channel.js +1 -0
  79. package/dist/src/public/channels/slack/defaults.d.ts +7 -3
  80. package/dist/src/public/channels/slack/defaults.js +3 -3
  81. package/dist/src/public/channels/slack/hitl.d.ts +7 -17
  82. package/dist/src/public/channels/slack/hitl.js +1 -1
  83. package/dist/src/public/channels/slack/index.d.ts +4 -3
  84. package/dist/src/public/channels/slack/index.js +1 -1
  85. package/dist/src/public/channels/slack/interaction-cards.d.ts +0 -2
  86. package/dist/src/public/channels/slack/interaction-cards.js +1 -1
  87. package/dist/src/public/channels/slack/interactions.js +1 -1
  88. package/dist/src/public/channels/slack/open-code-channel.d.ts +30 -0
  89. package/dist/src/public/channels/slack/open-code-channel.js +1 -0
  90. package/dist/src/public/channels/slack/private-approval-delivery.d.ts +16 -4
  91. package/dist/src/public/channels/slack/private-approval-delivery.js +1 -1
  92. package/dist/src/public/channels/slack/renderers.d.ts +58 -6
  93. package/dist/src/public/channels/slack/renderers.js +1 -1
  94. package/dist/src/public/channels/slack/reply-delivery.d.ts +4 -0
  95. package/dist/src/public/channels/slack/reply-delivery.js +1 -1
  96. package/dist/src/public/channels/slack/request-card-render.d.ts +45 -0
  97. package/dist/src/public/channels/slack/request-card-render.js +1 -0
  98. package/dist/src/public/channels/slack/request-cards.d.ts +35 -0
  99. package/dist/src/public/channels/slack/request-cards.js +3 -0
  100. package/dist/src/public/channels/slack/sign-in-cancel.d.ts +3 -5
  101. package/dist/src/public/channels/slack/sign-in-cancel.js +1 -1
  102. package/dist/src/public/channels/slack/slackChannel.d.ts +109 -22
  103. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  104. package/dist/src/public/channels/slack/task-card.d.ts +3 -3
  105. package/dist/src/public/channels/slack/task-card.js +1 -1
  106. package/dist/src/public/channels/slack/thread-status.js +1 -1
  107. package/dist/src/public/channels/teams/api.js +1 -1
  108. package/dist/src/public/channels/teams/defaults.js +1 -1
  109. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  110. package/dist/src/public/channels/teams/verify.d.ts +9 -5
  111. package/dist/src/public/channels/teams/verify.js +1 -1
  112. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  113. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  114. package/dist/src/public/schedules/subscription.d.ts +10 -1
  115. package/dist/src/runtime/subagents/workflow.js +1 -1
  116. package/dist/src/setup/index.d.ts +1 -1
  117. package/dist/src/setup/primitives/index.d.ts +1 -1
  118. package/dist/src/setup/primitives/pm/run.d.ts +0 -2
  119. package/dist/src/setup/scaffold/create/project.js +1 -1
  120. package/dist/src/shared/channel-definition.d.ts +4 -4
  121. package/dist/src/subagents/adapter.js +1 -1
  122. package/dist/src/subagents/parent-notification.js +1 -1
  123. package/dist/src/svelte/index.js +1 -1
  124. package/dist/src/svelte/use-eve-agent.js +1 -1
  125. package/dist/src/tools/definition.d.ts +21 -0
  126. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  127. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  128. package/dist/src/tools/workflow-definition.d.ts +4 -4
  129. package/dist/src/vue/index.js +1 -1
  130. package/dist/src/vue/use-eve-agent.js +1 -1
  131. package/docs/channels/custom.mdx +16 -3
  132. package/docs/channels/eve.mdx +2 -0
  133. package/docs/channels/linq.mdx +1 -1
  134. package/docs/channels/slack.mdx +185 -18
  135. package/docs/channels/teams.mdx +6 -2
  136. package/docs/concepts/upgrade-to-v27-events.md +2 -2
  137. package/docs/experimental/dynamic-schedules.mdx +2 -2
  138. package/docs/guides/client/overview.mdx +1 -1
  139. package/docs/guides/remote-agents.md +8 -0
  140. package/docs/patterns/fork-conversations-into-new-threads.md +159 -0
  141. package/docs/patterns/meta.json +1 -0
  142. package/docs/schedules.mdx +1 -1
  143. package/docs/tools/overview.mdx +34 -0
  144. package/docs/tools/workflows.mdx +47 -5
  145. package/package.json +1 -1
  146. package/dist/src/public/channels/slack/approval-cards.d.ts +0 -25
  147. package/dist/src/public/channels/slack/approval-cards.js +0 -2
@@ -1 +1 @@
1
- import{FACT_CATALOG,isFactType}from"#protocol/session-events/catalog.js";import{copyView}from"#protocol/session-projection/fold.js";import{createLogger}from"#internal/logging.js";import{callAdapterEventHandler}from"#channel/adapter.js";import{contextStorage}from"#context/container.js";import{AuthKey,InitiatorAuthKey,ParentSessionKey,SessionKey}from"#context/keys.js";import{encodeLineBytes}from"#protocol/session-events/envelope.js";import{eventsOfLine,linesOf}from"#protocol/session-lines.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{SESSION_PROJECTION_STATE_KEY,storedProjection}from"#harness/session-machine/view.js";import{advance,currentProjection,currentView,enterSessionProjection,enterSessionProjectionAt,nextLinePosition,recordPublishedLine,saveSessionProjection}from"#harness/session-machine/current.js";import{readSessionStreamTailIndex,streamSessionLines}from"#execution/session-event-stream.js";import{getStepMetadata}from"#compiled/@workflow/core/index.js";import{withContextScope}from"#context/run-step.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{createDurableSessionState,readDurableSession,replaceDurableSessionSnapshot}from"#execution/durable-session-store.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{hydrateDurableSession}from"#execution/session.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{sessionEndedFacts}from"#harness/facts.js";import{initialSessionProjection}from"#protocol/session-projection.js";import{setChannelContext}from"#execution/channel-context.js";import{runReactions}from"#reactions/runner.js";import{forwardSessionInput}from"#execution/forward-session-input.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{announceWaiting}from"#harness/session-machine/waiting.js";import{cascade}from"#harness/session-machine/cascade.js";import{eventsOf}from"#harness/publication.js";import{bindSessionInstrumentation}from"#instrumentation/runtime.js";import{createStreamChecker}from"#protocol/session-events/checker.js";const log=createLogger(`execution.publish-session-events`);async function publishSessionEvents(e,t,n){let r=!1;return{...await publishEventsFromStep(e,`own`,t,n?.canCancelTurn?()=>{r=!0}:void 0),cancelled:r}}async function publishEventsFromStep(e,t,n,r){if(n.length===0)return{serializedContext:e.serializedContext,sessionState:e.sessionState};let{published:i}=await publishFromSessionStep(await restoreSessionStep(e),{cancelTurn:r,origin:t,async publish(e){await e(n)}});return i}async function restoreSessionStep(e){return{ctx:await deserializeContext(e.serializedContext),durableSession:readDurableSession(e.sessionState),sessionWritable:e.sessionWritable}}async function publishFromSessionStep(e,t){let{ctx:n}=e,r=await publishInSessionScope(e,t),i=t.updateSession?.(r.session,r.result)??{session:r.session},a=readSessionProjection(n),o=reconcileSessionContinuationToken(n,saveSessionProjection(dropClosedRecords(i.session,a),n));return{published:{serializedContext:serializeContext(n),sessionState:createDurableSessionState({session:o}),...`history`in o&&{history:o.history}},result:i.result}}async function publishInSessionScope(e,t){let{ctx:n}=e;enterSessionProjection(n,e.durableSession.state);let r=await readOrphanedLines({sessionId:e.durableSession.sessionId,position:nextLinePosition(n),sessionWritable:e.sessionWritable}),i=resolveEffectiveAgentRuntime(n.require(BundleKey),n),a=hydrateDurableSession({compactionOverrides:{thresholdPercent:i.thresholdPercent},durable:e.durableSession,turnAgent:i.turnAgent}),o=e.history===void 0?a:{...a,history:validateHarnessModelMessages(e.history)},s=t.origin===`own`?bindSessionInstrumentation({agentName:i.turnAgent.id,ctx:n,rootSessionId:o.rootSessionId??o.sessionId,sessionId:o.sessionId}):void 0,c=openSessionEventPublisher({cancelTurn:t.cancelTurn,ctx:n,inputSource:t.inputSource,orphaned:r,origin:t.origin,sessionWritable:e.sessionWritable});try{return await withContextScope(n,o,async e=>{let n=s?.createHandleEvent({handleEvent:c.publish})??c.publish,r=await t.publish(n,e);return await c.finish(),{result:r,session:e}})}finally{await s?.flush(),c.writer.release()}}function checksSessionEvents(){let e=process.env.EVE_CHECK_SESSION_EVENTS;return e===`1`||e!==`0`&&process.env.EVE_DEV===`1`}const interruptedAttempts=new WeakMap;async function readOrphanedLines(e){if(e.always!==!0&&!isRetriedStep())return[];let{sessionId:t,sessionWritable:n,position:r}=e,i=interruptedAttempts.get(n);return i===void 0&&(i=await readLinesFrom(t,r),interruptedAttempts.set(n,i)),i.filter(({position:e})=>e>=r)}function followInterruptedAttempt(e,t){let n=readDurableSession(t),r=storedProjection(n.state),i=(interruptedAttempts.get(e)??[]).filter(({position:e})=>e>=r.view.position);return i.length===0?t:(log.error(`a retried step wrote less than its interrupted attempt; the session follows the stream`,{lines:i.length,sessionId:t.sessionId}),replaceDurableSessionSnapshot({session:{...n,state:{...n.state,[SESSION_PROJECTION_STATE_KEY]:foldOrphanedLines(r,i)}},state:t}))}function isRetriedStep(){try{return getStepMetadata().attempt>1}catch(e){if(e instanceof Error&&e.name===`NotInStepContextError`)return!1;throw e}}async function readLinesFrom(e,t){let n=await readSessionStreamTailIndex(e);if(n+1<t)throw Error(`Session checkpoint is ahead of its stream.`);let r=[];if(n<t)return r;let i=t;for await(let a of streamSessionLines(e,{follow:!1,startIndex:t})){if(a.position>n)break;if(a.line===void 0||a.position!==i)throw Error(`Cannot reconcile an unreadable or missing session line.`);r.push({line:a.line,position:i++})}if(i!==n+1)throw Error(`Session stream ended before its reported tail.`);return r}function foldOrphanedLines(e,t){let n=e;for(let{line:e,position:r}of t){let t=`facts`in e?eventsOfLine(e,r,e.at):[];n=advance(n,e,r,t)}return n}async function reconcilePublishedSessionLines(e,t){let n=e??initialSessionProjection();return foldOrphanedLines(n,await readLinesFrom(t,n.view.position))}function sameLine(e,t){if(`progress`in t||`progress`in e)return`progress`in t&&`progress`in e&&JSON.stringify(e.progress)===JSON.stringify(t.progress);let identity=e=>{let{data:t,type:n}=e;if(!isFactType(n))return String(n);let r=t[FACT_CATALOG[n].idField];return`${n}:${String(r)}`};return e.facts.length===t.facts.length&&e.facts.every((e,n)=>identity(e)===identity(t.facts[n]))}function openSessionEventPublisher(e){let{ctx:t}=e,n=[...e.orphaned??[]],r=createSessionEventDispatcher(e),i=openSessionEventWriter(e.sessionWritable),a,o,emitOne=async e=>{if(a===void 0&&checksSessionEvents()){let{schemaViolation:e}=await import(`#protocol/session-events/schemas.js`);a=createStreamChecker({seed:currentProjection(t).view,validate:e})}o===void 0&&(o=copyView(currentView(t)));let s=cascade(currentView(t),eventsOf(e)),c=new Date().toISOString(),l=[],u=linesOf(s,c).map(e=>({line:e,bytes:encodeLineBytes(e)}));u.forEach(({line:e},n)=>{let r=a?.check(e,nextLinePosition(t)+n);if(r!==void 0&&r.length>0)throw a=void 0,Error(`Session event contract: ${r.map(e=>`${e.rule} at ${e.position}:${e.index??`progress`}: ${e.message}`).join(`; `)}`)});for(let{line:e,bytes:r}of u){let o=nextLinePosition(t),s=n[0];if(s!==void 0){if(s.position!==o||!sameLine(s.line,e))throw Error(`A retried step published differently from its interrupted attempt.`);n.shift();let r=`facts`in s.line?s.line.at:c;recordPublishedLine(t,s.line,o,eventsOfLine(s.line,o,r));continue}await i.write(r).catch(e=>{throw a=void 0,e});let u=eventsOfLine(e,o,c);recordPublishedLine(t,e,o,u);let d=`progress`in e,f=currentView(t);u.forEach(e=>l.push({event:e,position:e.meta.position,progress:d,view:f}))}return await r.deliver(l),l},s=Promise.resolve(),emit=e=>{let t=s.then(()=>emitOne(e));return s=t.then(()=>void 0,()=>void 0),t},publish=async t=>{let n=e.cancelTurn;await r.react(await emit(t),n===void 0?void 0:{cancelTurn:()=>n()})};return{dispatcher:r,writer:i,emit,publish,async finish(e){if(o===void 0)return;let n=e?.announce===!1?[]:announceWaiting(o,currentView(t));o=void 0,n.length>0&&await publish(n)}}}function createSessionEventDispatcher(e){let{ctx:t,inputSource:n}=e,r=t.require(ChannelKey),i=buildAdapterContext(r,t),a=n===void 0?i:{...i,inputSource:n},o=Promise.resolve();return{adapterCtx:i,async deliver(e){if(e.length===0)return;let o,committed=async()=>{if(o===void 0)return;let{facts:e,position:t,view:n}=o;o=void 0,await callAdapterEventHandler(r,{facts:e,position:t.line},{...a,position:t,scope:void 0,view:n})};for(let{event:i,position:s,progress:c,view:l}of e){if(o!==void 0&&o.position.line!==s.line&&await committed(),await forwardSessionInput(t,i,n))continue;c||(o??={facts:[],position:s,view:l}).facts.push(i);let e=`scope`in i?i.scope:void 0;await callAdapterEventHandler(r,i,{...a,position:s,scope:e,view:l})}await committed(),setChannelContext(t,{...r,state:{...i.state}})},react(e,n){if(e.length===0)return Promise.resolve();let r=o.then(()=>runReactions(t,{...n,written:e}));return o=r.catch(()=>void 0),r}}}function openSessionEventWriter(e){let t=e.getWriter(),n=!1,release=()=>{n||(n=!0,t.releaseLock())};return{async write(e){await t.write(e)},close:async()=>{try{await t.close()}finally{release()}},release}}function readSessionProjection(e){return currentProjection(e)}async function publishTerminalSessionEvent(e){let t=e.serializedContext[`eve.sessionId`]??``,n={errorId:e.errorId,sessionId:t},r=`session.ended`,i=e.projection??(e.sessionState===void 0?void 0:storedProjection(readDurableSession(e.sessionState).state));try{i=await reconcilePublishedSessionLines(i,t)}catch(e){throw log.error(`failed to fold the published tail for terminal ${r} event`,{...n,error:e}),e}let a,o;try{a=await deserializeContext(e.serializedContext),enterSessionProjectionAt(a,i),o=openSessionEventPublisher({ctx:a,origin:`own`,sessionWritable:e.sessionWritable})}catch(t){if(log.error(`failed to restore context for terminal ${r} event`,{...n,error:t}),i.view.session.status===`ended`){try{await openSessionEventWriter(e.sessionWritable).close()}catch{}return}let a=cascade(i.view,sessionEndedFacts(i,e.ending));await writeUnroutedSessionEvent(e.sessionWritable,a).catch(e=>log.error(`failed to write terminal ${r} event`,{...n,error:e}));return}if(i.view.session.status===`ended`){try{await o.writer.close()}catch{}finally{o.writer.release()}return}let s=a.get(AuthKey)??null;a.setVirtualContext(SessionKey,{auth:{current:s,initiator:a.get(InitiatorAuthKey)??s},parent:a.get(ParentSessionKey),sessionId:t,turn:e.turn??{id:`turn_0`,sequence:0}});let publish=async e=>{await o.emit(e),await o.writer.close()},c;try{c=bindSessionInstrumentation({agentName:a.require(BundleKey).turnAgent.id,ctx:a,rootSessionId:a.get(ParentSessionKey)?.rootSessionId??t,sessionId:t})}catch(e){log.error(`failed to bind instrumentation for terminal ${r} event`,{...n,error:e})}let l=c?.createHandleEvent({handleEvent:publish})??publish;try{await contextStorage.run(a,()=>l(sessionEndedFacts(i,e.ending)))}catch(e){log.error(`failed to publish terminal ${r} event`,{...n,error:e})}finally{o.writer.release();try{await c?.flush()}catch(e){log.error(`failed to flush instrumentation after terminal ${r} event`,{...n,error:e})}}}async function writeUnroutedSessionEvent(e,t){let n=openSessionEventWriter(e);try{let e=linesOf(t,new Date().toISOString()).map(encodeLineBytes);for(let t of e)await n.write(t);await n.close()}finally{n.release()}}async function commitSessionStep(e,t,n){let{state:r}=`ctx`in e?e.durableSession:readDurableSession(e.sessionState),i=sessionView(storedProjection(r),r),a=t(i);if(a.length>1&&a.some(e=>e.turn!==i.turn)||a.filter(e=>e.signIns!==void 0).length>1)throw Error(`A transition batch must not overlap turn or sign-in snapshots.`);return`ctx`in e?await commit(e,a,n):a.every(e=>changesNothing(i,e))?{serializedContext:e.serializedContext,sessionState:e.sessionState}:await commit(await restoreSessionStep(e),a,n)}async function commit(e,t,n){let{published:r}=await publishFromSessionStep(e,{inputSource:n.inputSource,cancelTurn:n.cancelTurn,origin:n.origin,async publish(e){let n=t.flatMap(e=>e.events);n.length>0&&await e(n)},updateSession:e=>({session:t.reduce((e,t)=>saveTransition(e,t),e)})});return r}function changesNothing(e,t){return t.turn===e.turn&&t.events.length===0&&t.signIns===void 0&&t.relays===void 0&&t.commit===void 0&&t.clearsHistory===void 0}export{checksSessionEvents,commitSessionStep,foldOrphanedLines,followInterruptedAttempt,openSessionEventPublisher,publishFromSessionStep,publishSessionEvents,publishTerminalSessionEvent,readOrphanedLines,readSessionProjection,restoreSessionStep};
1
+ import{FACT_CATALOG,isFactType}from"#protocol/session-events/catalog.js";import{copyView}from"#protocol/session-projection/fold.js";import{createLogger}from"#internal/logging.js";import{callAdapterEventHandler}from"#channel/adapter.js";import{contextStorage}from"#context/container.js";import{AuthKey,InitiatorAuthKey,ParentSessionKey,SessionKey}from"#context/keys.js";import{encodeLineBytes}from"#protocol/session-events/envelope.js";import{eventsOfLine,linesOf}from"#protocol/session-lines.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{SESSION_PROJECTION_STATE_KEY,storedProjection}from"#harness/session-machine/view.js";import{advance,currentProjection,currentView,enterSessionProjection,enterSessionProjectionAt,nextLinePosition,recordPublishedLine,saveSessionProjection}from"#harness/session-machine/current.js";import{readSessionStreamTailIndex,streamSessionLines}from"#execution/session-event-stream.js";import{getStepMetadata}from"#compiled/@workflow/core/index.js";import{withContextScope}from"#context/run-step.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{createDurableSessionState,readDurableSession,replaceDurableSessionSnapshot}from"#execution/durable-session-store.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{hydrateDurableSession}from"#execution/session.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{initialSessionProjection}from"#protocol/session-projection.js";import{sessionEndedFacts}from"#harness/facts.js";import{setChannelContext}from"#execution/channel-context.js";import{runReactions}from"#reactions/runner.js";import{forwardSessionInput}from"#execution/forward-session-input.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{announceWaiting}from"#harness/session-machine/waiting.js";import{cascade}from"#harness/session-machine/cascade.js";import{eventsOf}from"#harness/publication.js";import{bindSessionInstrumentation}from"#instrumentation/runtime.js";import{createStreamChecker}from"#protocol/session-events/checker.js";const log=createLogger(`execution.publish-session-events`);async function publishSessionEvents(e,t,n){let r=!1;return{...await publishEventsFromStep(e,`own`,t,n?.canCancelTurn?()=>{r=!0}:void 0),cancelled:r}}async function publishEventsFromStep(e,t,n,r){if(n.length===0)return{serializedContext:e.serializedContext,sessionState:e.sessionState};let{published:i}=await publishFromSessionStep(await restoreSessionStep(e),{cancelTurn:r,origin:t,async publish(e){await e(n)}});return i}async function restoreSessionStep(e){return{ctx:await deserializeContext(e.serializedContext),durableSession:readDurableSession(e.sessionState),sessionWritable:e.sessionWritable}}async function publishFromSessionStep(e,t){let{ctx:n}=e,r=await publishInSessionScope(e,t),i=t.updateSession?.(r.session,r.result)??{session:r.session},a=readSessionProjection(n),o=reconcileSessionContinuationToken(n,saveSessionProjection(dropClosedRecords(i.session,a),n));return{published:{serializedContext:serializeContext(n),sessionState:createDurableSessionState({session:o}),...`history`in o&&{history:o.history}},result:i.result}}async function publishInSessionScope(e,t){let{ctx:n}=e;enterSessionProjection(n,e.durableSession.state);let r=await readOrphanedLines({sessionId:e.durableSession.sessionId,position:nextLinePosition(n),sessionWritable:e.sessionWritable}),i=resolveEffectiveAgentRuntime(n.require(BundleKey),n),a=hydrateDurableSession({compactionOverrides:{thresholdPercent:i.thresholdPercent},durable:e.durableSession,turnAgent:i.turnAgent}),o=e.history===void 0?a:{...a,history:validateHarnessModelMessages(e.history)},s=t.origin===`own`?bindSessionInstrumentation({agentName:i.turnAgent.id,ctx:n,rootSessionId:o.rootSessionId??o.sessionId,sessionId:o.sessionId}):void 0,c=openSessionEventPublisher({cancelTurn:t.cancelTurn,ctx:n,inputSource:t.inputSource,orphaned:r,origin:t.origin,sessionWritable:e.sessionWritable});try{return await withContextScope(n,o,async e=>{let n=s?.createHandleEvent({handleEvent:c.publish})??c.publish,r=await t.publish(n,e);return await c.finish(),{result:r,session:e}})}finally{await s?.flush(),c.writer.release()}}function checksSessionEvents(){let e=process.env.EVE_CHECK_SESSION_EVENTS;return e===`1`||e!==`0`&&process.env.EVE_DEV===`1`}const interruptedAttempts=new WeakMap;async function readOrphanedLines(e){if(e.always!==!0&&!isRetriedStep())return[];let{sessionId:t,sessionWritable:n,position:r}=e,i=interruptedAttempts.get(n);return i===void 0&&(i=await readLinesFrom(t,r),interruptedAttempts.set(n,i)),i.filter(({position:e})=>e>=r)}function followInterruptedAttempt(e,t){let n=readDurableSession(t),r=storedProjection(n.state),i=(interruptedAttempts.get(e)??[]).filter(({position:e})=>e>=r.view.position);return i.length===0?t:(log.error(`a retried step wrote less than its interrupted attempt; the session follows the stream`,{lines:i.length,sessionId:t.sessionId}),replaceDurableSessionSnapshot({session:{...n,state:{...n.state,[SESSION_PROJECTION_STATE_KEY]:foldOrphanedLines(r,i)}},state:t}))}function isRetriedStep(){try{return getStepMetadata().attempt>1}catch(e){if(e instanceof Error&&e.name===`NotInStepContextError`)return!1;throw e}}async function readLinesFrom(e,t){let n=await readSessionStreamTailIndex(e);if(n+1<t)throw Error(`Session checkpoint is ahead of its stream.`);let r=[];if(n<t)return r;let i=t;for await(let a of streamSessionLines(e,{follow:!1,startIndex:t})){if(a.position>n)break;if(a.line===void 0||a.position!==i)throw Error(`Cannot reconcile an unreadable or missing session line.`);r.push({line:a.line,position:i++})}if(i!==n+1)throw Error(`Session stream ended before its reported tail.`);return r}function foldOrphanedLines(e,t){let n=e;for(let{line:e,position:r}of t){let t=`facts`in e?eventsOfLine(e,r,e.at):[];n=advance(n,e,r,t)}return n}async function reconcilePublishedSessionLines(e,t){let n=e??initialSessionProjection();return foldOrphanedLines(n,await readLinesFrom(t,n.view.position))}function sameLine(e,t){if(`progress`in t||`progress`in e)return`progress`in t&&`progress`in e&&JSON.stringify(e.progress)===JSON.stringify(t.progress);let identity=e=>{let{data:t,type:n}=e;if(!isFactType(n))return String(n);let r=t[FACT_CATALOG[n].idField];return`${n}:${String(r)}`};return e.facts.length===t.facts.length&&e.facts.every((e,n)=>identity(e)===identity(t.facts[n]))}function openSessionEventPublisher(e){let{ctx:t}=e,n=[...e.orphaned??[]],r=createSessionEventDispatcher(e),i=openSessionEventWriter(e.sessionWritable),a,o,emitOne=async e=>{if(a===void 0&&checksSessionEvents()){let{schemaViolation:e}=await import(`#protocol/session-events/schemas.js`);a=createStreamChecker({seed:currentProjection(t).view,validate:e})}o===void 0&&(o=copyView(currentView(t)));let s=cascade(currentView(t),eventsOf(e)),c=new Date().toISOString(),l=[],u=linesOf(s,c).map(e=>({line:e,bytes:encodeLineBytes(e)}));u.forEach(({line:e},n)=>{let r=a?.check(e,nextLinePosition(t)+n);if(r!==void 0&&r.length>0)throw a=void 0,Error(`Session event contract: ${r.map(e=>`${e.rule} at ${e.position}:${e.index??`progress`}: ${e.message}`).join(`; `)}`)});for(let{line:e,bytes:r}of u){let o=nextLinePosition(t),s=n[0];if(s!==void 0){if(s.position!==o||!sameLine(s.line,e))throw Error(`A retried step published differently from its interrupted attempt.`);n.shift();let r=`facts`in s.line?s.line.at:c;recordPublishedLine(t,s.line,o,eventsOfLine(s.line,o,r));continue}await i.write(r).catch(e=>{throw a=void 0,e});let u=eventsOfLine(e,o,c);recordPublishedLine(t,e,o,u);let d=`progress`in e,f=currentView(t);u.forEach(e=>l.push({event:e,position:e.meta.position,progress:d,view:f}))}return await r.deliver(l),l},s=Promise.resolve(),emit=e=>{let t=s.then(()=>emitOne(e));return s=t.then(()=>void 0,()=>void 0),t},publish=async t=>{let n=e.cancelTurn;await r.react(await emit(t),n===void 0?void 0:{cancelTurn:()=>n()})};return{dispatcher:r,writer:i,emit,publish,async finish(e){if(o===void 0)return;let n=e?.announce===!1?[]:announceWaiting(o,currentView(t));o=void 0,n.length>0&&await publish(n)}}}function createSessionEventDispatcher(e){let{ctx:t,inputSource:n}=e,r=t.require(ChannelKey),i=buildAdapterContext(r,t),a=n===void 0?i:{...i,inputSource:n},o=Promise.resolve();return{adapterCtx:i,async deliver(e){if(e.length===0)return;let o,committed=async()=>{if(o===void 0)return;let{facts:e,position:t,view:n}=o;o=void 0,await callAdapterEventHandler(r,{facts:e,position:t.line},{...a,position:t,scope:void 0,view:n})};for(let{event:i,position:s,progress:c,view:l}of e){if(o!==void 0&&o.position.line!==s.line&&await committed(),await forwardSessionInput(t,i,n))continue;c||(o??={facts:[],position:s,view:l}).facts.push(i);let e=`scope`in i?i.scope:void 0;await callAdapterEventHandler(r,i,{...a,position:s,scope:e,view:l})}await committed(),setChannelContext(t,{...r,state:{...i.state}})},react(e,n){if(e.length===0)return Promise.resolve();let r=o.then(()=>runReactions(t,{...n,written:e}));return o=r.catch(()=>void 0),r}}}function openSessionEventWriter(e){let t=e.getWriter(),n=!1,release=()=>{n||(n=!0,t.releaseLock())};return{async write(e){await t.write(e)},close:async()=>{try{await t.close()}finally{release()}},release}}function readSessionProjection(e){return currentProjection(e)}async function publishTerminalSessionEvent(e){let t=e.serializedContext[`eve.sessionId`]??``,n={errorId:e.errorId,sessionId:t},r=`session.ended`,i=e.projection??(e.sessionState===void 0?void 0:storedProjection(readDurableSession(e.sessionState).state));try{i=await reconcilePublishedSessionLines(i,t)}catch(e){throw log.error(`failed to fold the published tail for terminal ${r} event`,{...n,error:e}),e}let a,o;try{a=await deserializeContext(e.serializedContext),enterSessionProjectionAt(a,i),o=openSessionEventPublisher({ctx:a,origin:`own`,sessionWritable:e.sessionWritable})}catch(t){if(log.error(`failed to restore context for terminal ${r} event`,{...n,error:t}),i.view.session.status===`ended`){try{await openSessionEventWriter(e.sessionWritable).close()}catch{}return}let a=cascade(i.view,sessionEndedFacts(i,e.ending));await writeUnroutedSessionEvent(e.sessionWritable,a).catch(e=>log.error(`failed to write terminal ${r} event`,{...n,error:e}));return}if(i.view.session.status===`ended`){try{await o.writer.close()}catch{}finally{o.writer.release()}return}let s=a.get(AuthKey)??null;a.setVirtualContext(SessionKey,{auth:{current:s,initiator:a.get(InitiatorAuthKey)??s},parent:a.get(ParentSessionKey),sessionId:t,turn:e.turn??{id:`turn_0`,sequence:0}});let publish=async e=>{await o.emit(e),await o.writer.close()},c;try{c=bindSessionInstrumentation({agentName:a.require(BundleKey).turnAgent.id,ctx:a,rootSessionId:a.get(ParentSessionKey)?.rootSessionId??t,sessionId:t})}catch(e){log.error(`failed to bind instrumentation for terminal ${r} event`,{...n,error:e})}let l=c?.createHandleEvent({handleEvent:publish})??publish;try{await contextStorage.run(a,()=>l(sessionEndedFacts(i,e.ending)))}catch(e){log.error(`failed to publish terminal ${r} event`,{...n,error:e})}finally{o.writer.release();try{await c?.flush()}catch(e){log.error(`failed to flush instrumentation after terminal ${r} event`,{...n,error:e})}}}async function writeUnroutedSessionEvent(e,t){let n=openSessionEventWriter(e);try{let e=linesOf(t,new Date().toISOString()).map(encodeLineBytes);for(let t of e)await n.write(t);await n.close()}finally{n.release()}}async function commitSessionStep(e,t,n){let{state:r}=`ctx`in e?e.durableSession:readDurableSession(e.sessionState),i=sessionView(storedProjection(r),r),a=t(i);if(a.length>1&&a.some(e=>e.turn!==i.turn)||a.filter(e=>e.signIns!==void 0).length>1)throw Error(`A transition batch must not overlap turn or sign-in snapshots.`);return`ctx`in e?await commit(e,a,n):a.every(e=>changesNothing(i,e))?{serializedContext:e.serializedContext,sessionState:e.sessionState}:await commit(await restoreSessionStep(e),a,n)}async function commit(e,t,n){let{published:r}=await publishFromSessionStep(e,{inputSource:n.inputSource,cancelTurn:n.cancelTurn,origin:n.origin,async publish(e){let n=t.flatMap(e=>e.events);n.length>0&&await e(n)},updateSession:e=>({session:t.reduce((e,t)=>saveTransition(e,t),e)})});return r}function changesNothing(e,t){return t.turn===e.turn&&t.events.length===0&&t.signIns===void 0&&t.relays===void 0&&t.commit===void 0&&t.clearsHistory===void 0}export{checksSessionEvents,commitSessionStep,foldOrphanedLines,followInterruptedAttempt,openSessionEventPublisher,publishFromSessionStep,publishSessionEvents,publishTerminalSessionEvent,readOrphanedLines,readSessionProjection,restoreSessionStep};
@@ -1,13 +1,25 @@
1
1
  import { type SessionCheckpoint } from "#execution/session/handoff.js";
2
+ import { type PreV27Checkpoint } from "#execution/session/pre-v27-checkpoint.js";
2
3
  /**
3
- * Oldest checkpoint a successor accepts: the first that writes v27 session events. A session
4
- * whose stream began in the earlier shape stays on the deployment that owns it, since its
5
- * stream's lines, projection, and private records of running work changed shape together.
4
+ * Oldest checkpoint a successor upgrades in place: the first that writes v27 session events.
5
+ * Older ones, from an owner before v27, are imported instead (`pre-v27-checkpoint.ts`): their
6
+ * stream's lines, projection, and private records of running work changed shape together, so the
7
+ * successor also folds their stream before it continues.
6
8
  */
7
9
  export declare const MIN_SESSION_CHECKPOINT_VERSION = 18;
8
10
  export type SessionCheckpointMigration = {
9
11
  readonly kind: "current";
10
12
  readonly checkpoint: SessionCheckpoint;
13
+ }
14
+ /** A checkpoint from an owner before v27, still without the projection its stream holds. */
15
+ | {
16
+ readonly kind: "pre-v27";
17
+ readonly imported: PreV27Checkpoint;
18
+ }
19
+ /** An owner before v27 still runs work for the session; a later delivery can move it. */
20
+ | {
21
+ readonly kind: "busy";
22
+ readonly detail: string;
11
23
  } | {
12
24
  readonly kind: "incompatible";
13
25
  readonly detail: string;
@@ -15,7 +27,6 @@ export type SessionCheckpointMigration = {
15
27
  /**
16
28
  * Upgrades a checkpoint written by an older eve build to the current shape.
17
29
  * Pure, so the session workflow can run it before validation. Newer
18
- * checkpoints and those older than {@link MIN_SESSION_CHECKPOINT_VERSION} are
19
- * incompatible.
30
+ * checkpoints and those older than eve 0.69 are incompatible.
20
31
  */
21
32
  export declare function migrateSessionCheckpoint(checkpoint: unknown): SessionCheckpointMigration;
@@ -1 +1 @@
1
- import{isObject}from"#shared/guards.js";import{DELIVERY_IDEMPOTENCY_WINDOW,MAX_DELIVERY_IDEMPOTENCY_KEY_LENGTH}from"#channel/delivery-idempotency.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";const MIN_SESSION_CHECKPOINT_VERSION=18,CHECKPOINT_UPGRADES={};function migrateSessionCheckpoint(e){if(!isObject(e))return{kind:`incompatible`,detail:`checkpoint is not an object`};let{version:t}=e;if(typeof t==`number`&&t<18)return{kind:`incompatible`,detail:`checkpoint version ${t} predates v27 session events; the session continues on the deployment that owns it`};if(typeof t!=`number`||!Number.isSafeInteger(t)||t>SESSION_CHECKPOINT_VERSION)return{kind:`incompatible`,detail:`checkpoint version ${JSON.stringify(t)} is outside the supported range 18-${SESSION_CHECKPOINT_VERSION}`};let n=e;try{for(let e=t;e<SESSION_CHECKPOINT_VERSION;e++){let t=CHECKPOINT_UPGRADES[e];t===void 0&&refuse(`no upgrade from checkpoint version ${e}`),n={...t(n),version:e+1}}}catch(e){if(!(e instanceof CheckpointRefusal))throw e;return{kind:`incompatible`,detail:`checkpoint version ${t}: ${e.message}`}}return isCurrentCheckpoint(n)?{kind:`current`,checkpoint:n}:{kind:`incompatible`,detail:`checkpoint version ${t} is incomplete`}}function isCurrentCheckpoint(e){return isObject(e)&&e.version===SESSION_CHECKPOINT_VERSION&&Array.isArray(e.admittedDeliveryKeys)&&e.admittedDeliveryKeys.length<=DELIVERY_IDEMPOTENCY_WINDOW&&e.admittedDeliveryKeys.every(e=>typeof e==`string`&&e.length>0&&e.length<=MAX_DELIVERY_IDEMPOTENCY_KEY_LENGTH)&&Array.isArray(e.history)&&isObject(e.serializedContext)&&isObject(e.sessionState)}var CheckpointRefusal=class extends Error{};function refuse(e){throw new CheckpointRefusal(e)}export{MIN_SESSION_CHECKPOINT_VERSION,migrateSessionCheckpoint};
1
+ import{isObject}from"#shared/guards.js";import{DELIVERY_IDEMPOTENCY_WINDOW,MAX_DELIVERY_IDEMPOTENCY_KEY_LENGTH}from"#channel/delivery-idempotency.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";import{importPreV27Checkpoint,isPreV27CheckpointVersion}from"#execution/session/pre-v27-checkpoint.js";import{CheckpointRefusal,refuse}from"#execution/session/checkpoint-refusal.js";const MIN_SESSION_CHECKPOINT_VERSION=18,CHECKPOINT_UPGRADES={};function migrateSessionCheckpoint(e){if(!isObject(e))return{kind:`incompatible`,detail:`checkpoint is not an object`};let{version:t}=e;if(isPreV27CheckpointVersion(t)){let n=importPreV27Checkpoint({...e,version:t});if(n.kind!==`pre-v27`)return n;let{imported:r}=n;return isCurrentCheckpoint(r.checkpoint)?{kind:`pre-v27`,imported:{...r,checkpoint:r.checkpoint}}:{kind:`incompatible`,detail:`checkpoint version ${t} is incomplete`}}if(typeof t!=`number`||!Number.isSafeInteger(t)||t<18||t>SESSION_CHECKPOINT_VERSION)return{kind:`incompatible`,detail:`checkpoint version ${JSON.stringify(t)} is outside the supported ranges: 10-17 import, 18-${SESSION_CHECKPOINT_VERSION} upgrade`};let n=e;try{for(let e=t;e<SESSION_CHECKPOINT_VERSION;e++){let t=CHECKPOINT_UPGRADES[e];t===void 0&&refuse(`no upgrade from checkpoint version ${e}`),n={...t(n),version:e+1}}}catch(e){if(!(e instanceof CheckpointRefusal))throw e;return{kind:`incompatible`,detail:`checkpoint version ${t}: ${e.message}`}}return isCurrentCheckpoint(n)?{kind:`current`,checkpoint:n}:{kind:`incompatible`,detail:`checkpoint version ${t} is incomplete`}}function isCurrentCheckpoint(e){return isObject(e)&&e.version===SESSION_CHECKPOINT_VERSION&&Array.isArray(e.admittedDeliveryKeys)&&e.admittedDeliveryKeys.length<=DELIVERY_IDEMPOTENCY_WINDOW&&e.admittedDeliveryKeys.every(e=>typeof e==`string`&&e.length>0&&e.length<=MAX_DELIVERY_IDEMPOTENCY_KEY_LENGTH)&&Array.isArray(e.history)&&isObject(e.serializedContext)&&isObject(e.sessionState)}export{MIN_SESSION_CHECKPOINT_VERSION,migrateSessionCheckpoint};
@@ -0,0 +1,4 @@
1
+ /** State a checkpoint holds that this build cannot continue; the owner that wrote it keeps the session. */
2
+ export declare class CheckpointRefusal extends Error {
3
+ }
4
+ export declare function refuse(detail: string): never;
@@ -0,0 +1 @@
1
+ var CheckpointRefusal=class extends Error{};function refuse(e){throw new CheckpointRefusal(e)}export{CheckpointRefusal,refuse};
@@ -1 +1 @@
1
- import{attachClientContext,readClientContext}from"#internal/client-context.js";import{SESSION_INBOX_CONTEXT_KEY,sessionCommandHookToken}from"#execution/session-inbox/address.js";import{readSerializedSessionSchedule}from"#context/session-schedule.js";import{storedProjection}from"#harness/session-machine/view.js";import{createHook,getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";import{createSessionTimeoutControl}from"#execution/session/timeout-control.js";import{prepareSuccessorStep,signalSessionOwnerActivationStep}from"#execution/session/handoff-steps.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{readChannelRequestId,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{createTurnControl}from"#execution/session/turn-control.js";import{HANDOFF_LEASE_RETENTION,handoffLeaseToken,sendSessionHandover}from"#execution/session/handoff.js";import{resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createSessionStep}from"#execution/create-session-step.js";import{closeSessionStreamStep}from"#execution/close-session-stream-step.js";import{settleContinuationConflictStep}from"#execution/continuation-conflict-step.js";import{migrateSessionCheckpoint}from"#execution/session/checkpoint-migrations.js";import{abandonHandoverIfRunEnds,watchRunEnd}from"#execution/session/run-watch.js";async function workflowEntry(e){"use workflow";let t=e.kind===`initial`?await bootInitialOwner(e,getWorkflowMetadata().workflowRunId):(e.handoffVersion??0)>=3?await bootForcedHandoffOwner(e):await bootReleasedHandoffOwner(e);return t===void 0?{output:``}:{output:(await runPreparedSession(t.session,t.inbox)).output}}function stampSessionIdentity(e,t){return{...e,"eve.sessionId":t,[SESSION_INBOX_CONTEXT_KEY]:{sessionId:t}}}async function prepareInitialOwner(e,t){let n={kind:`owned`,timeoutControl:createSessionTimeoutControl({sessionId:t.sessionId,timeoutMs:t.sessionTimeoutMs}),turnControl:createTurnControl()},r={confirmAfter:t.sessionCreation},[i,a]=await Promise.allSettled([e.claimSessionHook(sessionCommandHookToken(t.sessionId),r),t.continuationToken===``?Promise.resolve():e.claimSessionHook(t.continuationToken,r)]);if(i.status===`rejected`)throw i.reason;if(a.status===`rejected`){if(isHookConflictError(a.reason))return{kind:`alias-conflict`};throw a.reason}return n}function unwrapSettled(e){if(e.status===`rejected`)throw e.reason;return e.value}async function bootInitialOwner(e,t){let n=stampSessionIdentity(e.serializedContext,t),r=getWritable(),i=createSessionInbox(t),a=e.sessionTimeoutMs??DEFAULT_SESSION_TIMEOUT_MS,o=n[`eve.continuationToken`]||``,s=n[`eve.bundle`];try{let c=createSessionStep({agentSessionRuntimeOverrides:n[`eve.agentSessionRuntimeOverrides`],compiledArtifactsSource:s.source,continuationToken:o,dynamicSubagentAgentConfig:n[`eve.dynamicSubagentAgentConfig`],history:e.input.message===void 0?e.input.history:void 0,nodeId:s.nodeId,outputSchema:e.input.outputSchema,rootSessionId:readRootSessionId(n),sessionId:t}),l=prepareInitialOwner(i,{continuationToken:o,sessionCreation:c,sessionId:t,sessionTimeoutMs:a}),u=hasDelegatedSessionContext(n)?resolveInitialTurnCallerStep({serializedContext:n}):Promise.resolve(void 0),[d,f,p]=await Promise.allSettled([c,l,u]),m=unwrapSettled(d),h=unwrapSettled(f);if(h.kind===`alias-conflict`){e.continuationConflictCommand!==void 0&&await settleContinuationConflictStep({command:e.continuationConflictCommand,continuationToken:o}),await i.dispose(),await closeSessionStreamStep({sessionWritable:r});return}let g=unwrapSettled(p);return{inbox:i,session:{admittedDeliveryKeys:e.idempotencyKey===void 0?[]:[e.idempotencyKey],anchor:{kind:`self`},caller:g,capabilities:n[`eve.capabilities`],deploymentId:e.ownerDeploymentId,history:m.history,start:e.input.message===void 0?{kind:`first-message`}:{input:createInitialDelivery(e,n),kind:`turn`},initialTurnControl:h.turnControl,retention:e.retention,serializedContext:n,sessionId:t,sessionState:m.state,sessionTimeoutControl:h.timeoutControl,sessionTimeoutMs:a,sessionWritable:r}}}catch(e){return await i.dispose(),await failSession({error:e,serializedContext:n,sessionId:t,sessionState:void 0,sessionWritable:r})}}async function prepareSuccessor(e,t){let{sessionId:n}=e,r=migrateSessionCheckpoint(e.checkpoint),i=await prepareSuccessorStep({handoffVersion:e.handoffVersion,migration:r,sessionId:n,...t!==void 0&&{source:t}});if(r.kind===`incompatible`||i.kind===`incompatible`){await signalSessionOwnerActivationStep({activation:{kind:`incompatible`,payloads:[],reason:`checkpoint-version`,runId:getWorkflowMetadata().workflowRunId},token:e.activationToken});return}if(i.kind===`source-gone`){await signalFailedActivation(e,Error(`The session's previous owner no longer holds all of its addresses.`),{payloads:[]});return}let{checkpoint:a}=r;return{checkpoint:a,serializedContext:stampSessionIdentity(a.serializedContext,n)}}async function signalFailedActivation(e,t,n){await signalSessionOwnerActivationStep({activation:{error:normalizeSerializableError(t),kind:`failed`,runId:getWorkflowMetadata().workflowRunId,...n},token:e.activationToken})}async function bootForcedHandoffOwner(e){let{attemptKey:t,hookTokens:n,sessionId:r,sourceRunId:i}=e;if(t===void 0||n===void 0||i===void 0){await signalFailedActivation(e,Error(`Session handoff version 3 input is missing attemptKey, hookTokens, or sourceRunId.`),{payloads:[]});return}try{let e=createHook({experimental_minRetention:HANDOFF_LEASE_RETENTION,token:handoffLeaseToken(t)});await claimHookOwnership(e)}catch(t){if(isHookConflictError(t))return;await signalFailedActivation(e,t,{payloads:[]});return}let a;try{a=await prepareSuccessor(e,{hookTokens:n,runId:i})}catch(t){await signalFailedActivation(e,t,{payloads:[]});return}if(a===void 0)return;let o=createSessionInbox(r);try{await o.claimSessionHooks(n,{force:!0,handover:t})}catch(n){let a=o.claimedTokens.length>0;await signalFailedActivation(e,n,{claimedHooks:a,payloads:[]}),a&&await handBack(o,{attemptKey:t,sessionId:r,sourceRunId:i}),await o.dispose();return}return abandonHandoverIfRunEnds(o,{attemptKey:t,sourceRunId:i}),await startSuccessor(e,o,a)}async function handBack(e,t){let n=watchRunEnd(t.sourceRunId),r=new AbortController;try{if(await Promise.race([e.whenTakenOver(r.signal).then(()=>`taken-back`),n.ended.then(()=>`source-ended`)])===`source-ended`)return}finally{n.stop(),r.abort()}await sendSessionHandover({attemptKey:t.attemptKey,payloads:e.drain(),sessionId:t.sessionId})}async function bootReleasedHandoffOwner(e){let t=createSessionInbox(e.sessionId),n;try{if(n=await prepareSuccessor(e),n===void 0)return;await t.claimSessionHooks(sessionHookTokens({serializedContext:n.serializedContext,sessionState:n.checkpoint.sessionState})),await signalSessionOwnerActivationStep({activation:{kind:`active`},token:e.activationToken})}catch(n){await signalFailedActivation(e,n,{payloads:await t.release()});return}return await startSuccessor(e,t,n)}async function startSuccessor(e,t,n){let{sessionId:r}=e,{checkpoint:i,serializedContext:a}=n;return{inbox:t,session:{anchor:{kind:`successor`},admittedDeliveryKeys:i.admittedDeliveryKeys,caller:e.delivery?.caller,capabilities:i.capabilities,deploymentId:e.ownerDeploymentId,history:i.history,start:e.delivery===void 0?storedProjection(i.sessionState.snapshot.session.state).view.session.status===`new`?{kind:`first-message`}:{kind:`parked`}:{input:e.delivery,kind:`turn`},retention:i.retention,serializedContext:a,sessionId:r,sessionState:i.sessionState,sessionTimeoutControl:createSessionTimeoutControl({deadline:e.reason===`prewarm`?e.sessionTimeoutDeadline:void 0,sessionId:r,timeoutMs:i.sessionTimeoutMs}),sessionTimeoutMs:i.sessionTimeoutMs,sessionWritable:e.sessionWritable}}}function createInitialDelivery(e,t){if(e.input.message!==void 0)return{auth:t[`eve.auth`],idempotencyKey:e.idempotencyKey,schedule:readSerializedSessionSchedule(t),deliveryMetadata:t[`eve.channelDelivery`]===void 0?void 0:[{...t[`eve.channelDelivery`],payloadIndex:0}],kind:`deliver`,payloads:[attachClientContext({message:e.input.message,context:e.input.context,history:e.input.history,outputSchema:e.input.outputSchema,state:e.input.state},readClientContext(e.input))],requestId:readChannelRequestId(t)}}workflowEntry.workflowId=`workflow//eve//workflowEntry`;export{bootInitialOwner,workflowEntry};
1
+ import{attachClientContext,readClientContext}from"#internal/client-context.js";import{SESSION_INBOX_CONTEXT_KEY,sessionCommandHookToken}from"#execution/session-inbox/address.js";import{readSerializedSessionSchedule}from"#context/session-schedule.js";import{storedProjection}from"#harness/session-machine/view.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{createHook,getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS}from"#execution/session/timeout.js";import{sessionHookTokens}from"#execution/session/hook-tokens.js";import{createSessionInbox}from"#execution/session-inbox/inbox.js";import{failSession,runPreparedSession}from"#execution/session/program.js";import{createSessionTimeoutControl}from"#execution/session/timeout-control.js";import{prepareSuccessorStep,readSessionStreamTailStep,signalSessionOwnerActivationStep}from"#execution/session/handoff-steps.js";import{readChannelRequestId,readRootSessionId}from"#execution/eve-workflow-attributes.js";import{createTurnControl}from"#execution/session/turn-control.js";import{HANDOFF_LEASE_RETENTION,handoffLeaseToken,sendSessionHandover}from"#execution/session/handoff.js";import{preV27Projection,withProjection}from"#execution/session/pre-v27-checkpoint.js";import{resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createSessionStep}from"#execution/create-session-step.js";import{closeSessionStreamStep}from"#execution/close-session-stream-step.js";import{settleContinuationConflictStep}from"#execution/continuation-conflict-step.js";import{migrateSessionCheckpoint}from"#execution/session/checkpoint-migrations.js";import{abandonHandoverIfRunEnds,watchRunEnd}from"#execution/session/run-watch.js";async function workflowEntry(e){"use workflow";let t=e.kind===`initial`?await bootInitialOwner(e,getWorkflowMetadata().workflowRunId):(e.handoffVersion??0)>=3?await bootForcedHandoffOwner(e):await bootReleasedHandoffOwner(e);return t===void 0?{output:``}:{output:(await runPreparedSession(t.session,t.inbox)).output}}function stampSessionIdentity(e,t){return{...e,"eve.sessionId":t,[SESSION_INBOX_CONTEXT_KEY]:{sessionId:t}}}async function prepareInitialOwner(e,t){let n={kind:`owned`,timeoutControl:createSessionTimeoutControl({sessionId:t.sessionId,timeoutMs:t.sessionTimeoutMs}),turnControl:createTurnControl()},r={confirmAfter:t.sessionCreation},[i,a]=await Promise.allSettled([e.claimSessionHook(sessionCommandHookToken(t.sessionId),r),t.continuationToken===``?Promise.resolve():e.claimSessionHook(t.continuationToken,r)]);if(i.status===`rejected`)throw i.reason;if(a.status===`rejected`){if(isHookConflictError(a.reason))return{kind:`alias-conflict`};throw a.reason}return n}function unwrapSettled(e){if(e.status===`rejected`)throw e.reason;return e.value}async function bootInitialOwner(e,t){let n=stampSessionIdentity(e.serializedContext,t),r=getWritable(),i=createSessionInbox(t),a=e.sessionTimeoutMs??DEFAULT_SESSION_TIMEOUT_MS,o=n[`eve.continuationToken`]||``,s=n[`eve.bundle`];try{let c=createSessionStep({agentSessionRuntimeOverrides:n[`eve.agentSessionRuntimeOverrides`],compiledArtifactsSource:s.source,continuationToken:o,dynamicSubagentAgentConfig:n[`eve.dynamicSubagentAgentConfig`],history:e.input.message===void 0?e.input.history:void 0,nodeId:s.nodeId,outputSchema:e.input.outputSchema,rootSessionId:readRootSessionId(n),sessionId:t}),l=prepareInitialOwner(i,{continuationToken:o,sessionCreation:c,sessionId:t,sessionTimeoutMs:a}),u=hasDelegatedSessionContext(n)?resolveInitialTurnCallerStep({serializedContext:n}):Promise.resolve(void 0),[d,f,p]=await Promise.allSettled([c,l,u]),m=unwrapSettled(d),h=unwrapSettled(f);if(h.kind===`alias-conflict`){e.continuationConflictCommand!==void 0&&await settleContinuationConflictStep({command:e.continuationConflictCommand,continuationToken:o}),await i.dispose(),await closeSessionStreamStep({sessionWritable:r});return}let g=unwrapSettled(p);return{inbox:i,session:{admittedDeliveryKeys:e.idempotencyKey===void 0?[]:[e.idempotencyKey],anchor:{kind:`self`},caller:g,capabilities:n[`eve.capabilities`],deploymentId:e.ownerDeploymentId,history:m.history,start:e.input.message===void 0?{kind:`first-message`}:{input:createInitialDelivery(e,n),kind:`turn`},initialTurnControl:h.turnControl,retention:e.retention,serializedContext:n,sessionId:t,sessionState:m.state,sessionTimeoutControl:h.timeoutControl,sessionTimeoutMs:a,sessionWritable:r}}}catch(e){return await i.dispose(),await failSession({error:e,serializedContext:n,sessionId:t,sessionState:void 0,sessionWritable:r})}}async function prepareSuccessor(e,t){let{sessionId:n}=e,r=migrateSessionCheckpoint(e.checkpoint);if(r.kind===`busy`){await signalFailedActivation(e,Error(r.detail),{payloads:[]});return}let i=await prepareSuccessorStep({handoffVersion:e.handoffVersion,migration:r,sessionId:n,...t!==void 0&&{source:t}});if(r.kind===`incompatible`||i.kind===`incompatible`){await signalSessionOwnerActivationStep({activation:{kind:`incompatible`,payloads:[],reason:`checkpoint-version`,runId:getWorkflowMetadata().workflowRunId},token:e.activationToken});return}if(i.kind===`source-gone`){await signalFailedActivation(e,Error(`The session's previous owner no longer holds all of its addresses.`),{payloads:[]});return}if(r.kind===`current`){let{checkpoint:e}=r;return{checkpoint:e,serializedContext:stampSessionIdentity(e.serializedContext,n)}}let{checkpoint:a,turnCount:o}=r.imported;return{checkpoint:a,importedTurnCount:o,serializedContext:stampSessionIdentity(a.serializedContext,n)}}async function placeImportedSession(e,t){if(t.importedTurnCount===void 0)return t;let n=await readSessionStreamTailStep({sessionId:e}),r=preV27Projection(n,t.importedTurnCount);return{...t,checkpoint:withProjection(t.checkpoint,r)}}async function signalFailedActivation(e,t,n){await signalSessionOwnerActivationStep({activation:{error:normalizeSerializableError(t),kind:`failed`,runId:getWorkflowMetadata().workflowRunId,...n},token:e.activationToken})}async function bootForcedHandoffOwner(e){let{attemptKey:t,hookTokens:n,sessionId:r,sourceRunId:i}=e;if(t===void 0||n===void 0||i===void 0){await signalFailedActivation(e,Error(`Session handoff version 3 input is missing attemptKey, hookTokens, or sourceRunId.`),{payloads:[]});return}try{let e=createHook({experimental_minRetention:HANDOFF_LEASE_RETENTION,token:handoffLeaseToken(t)});await claimHookOwnership(e)}catch(t){if(isHookConflictError(t))return;await signalFailedActivation(e,t,{payloads:[]});return}let a;try{a=await prepareSuccessor(e,{hookTokens:n,runId:i})}catch(t){await signalFailedActivation(e,t,{payloads:[]});return}if(a===void 0)return;let o=createSessionInbox(r);try{await o.claimSessionHooks(n,{force:!0,handover:t}),a=await placeImportedSession(r,a)}catch(n){let a=o.claimedTokens.length>0;await signalFailedActivation(e,n,{claimedHooks:a,payloads:[]}),a&&await handBack(o,{attemptKey:t,sessionId:r,sourceRunId:i}),await o.dispose();return}return abandonHandoverIfRunEnds(o,{attemptKey:t,sourceRunId:i}),await startSuccessor(e,o,a)}async function handBack(e,t){let n=watchRunEnd(t.sourceRunId),r=new AbortController;try{if(await Promise.race([e.whenTakenOver(r.signal).then(()=>`taken-back`),n.ended.then(()=>`source-ended`)])===`source-ended`)return}finally{n.stop(),r.abort()}await sendSessionHandover({attemptKey:t.attemptKey,payloads:e.drain(),sessionId:t.sessionId})}async function bootReleasedHandoffOwner(e){let t=createSessionInbox(e.sessionId),n;try{if(n=await prepareSuccessor(e),n===void 0)return;await t.claimSessionHooks(sessionHookTokens({serializedContext:n.serializedContext,sessionState:n.checkpoint.sessionState})),n=await placeImportedSession(e.sessionId,n),await signalSessionOwnerActivationStep({activation:{kind:`active`},token:e.activationToken})}catch(n){await signalFailedActivation(e,n,{payloads:await t.release()});return}return await startSuccessor(e,t,n)}async function startSuccessor(e,t,n){let{sessionId:r}=e,{checkpoint:i,serializedContext:a}=n;return{inbox:t,session:{anchor:{kind:`successor`},admittedDeliveryKeys:i.admittedDeliveryKeys,caller:e.delivery?.caller,capabilities:i.capabilities,compactFirst:n.importedTurnCount!==void 0&&i.history.length>0,deploymentId:e.ownerDeploymentId,history:i.history,start:e.delivery===void 0?storedProjection(i.sessionState.snapshot.session.state).view.session.status===`new`?{kind:`first-message`}:{kind:`parked`}:{input:e.delivery,kind:`turn`},retention:i.retention,serializedContext:a,sessionId:r,sessionState:i.sessionState,sessionTimeoutControl:createSessionTimeoutControl({deadline:e.reason===`prewarm`?e.sessionTimeoutDeadline:void 0,sessionId:r,timeoutMs:i.sessionTimeoutMs}),sessionTimeoutMs:i.sessionTimeoutMs,sessionWritable:e.sessionWritable}}}function createInitialDelivery(e,t){if(e.input.message!==void 0)return{auth:t[`eve.auth`],idempotencyKey:e.idempotencyKey,schedule:readSerializedSessionSchedule(t),deliveryMetadata:t[`eve.channelDelivery`]===void 0?void 0:[{...t[`eve.channelDelivery`],payloadIndex:0}],kind:`deliver`,payloads:[attachClientContext({message:e.input.message,context:e.input.context,history:e.input.history,outputSchema:e.input.outputSchema,state:e.input.state},readClientContext(e.input))],requestId:readChannelRequestId(t)}}workflowEntry.workflowId=`workflow//eve//workflowEntry`;export{bootInitialOwner,workflowEntry};
@@ -52,7 +52,9 @@ export type SessionCheckpointValidation = {
52
52
  export declare function prepareSuccessorStep(input: {
53
53
  /** Absent for version 1 sources, which predate the field. */
54
54
  readonly handoffVersion: number | undefined;
55
- readonly migration: SessionCheckpointMigration;
55
+ readonly migration: Exclude<SessionCheckpointMigration, {
56
+ readonly kind: "busy";
57
+ }>;
56
58
  readonly sessionId: string;
57
59
  /** Version 3: the run that still holds the session and the addresses it hands over. */
58
60
  readonly source?: {
@@ -114,3 +116,7 @@ export declare function signalSessionAnchorStep(input: {
114
116
  };
115
117
  readonly token: string;
116
118
  }): Promise<void>;
119
+ /** The position of the session stream's last line, or `-1` before the first. */
120
+ export declare function readSessionStreamTailStep(input: {
121
+ readonly sessionId: string;
122
+ }): Promise<number>;
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{getSandboxEnvironmentRuntime}from"#shared/sandbox-environment.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{getWorld,resumeHook}from"#internal/workflow/runtime.js";import{hasRunEnded,startWorkflowOnDeployment,workflowEntryReference}from"#execution/workflow-runtime.js";import{getResolvedRuntimeAgentNode}from"#runtime/graph.js";import{IncompatibleStateLayoutError,deserializeContext}from"#context/serialize.js";import{readDurableSession}from"#execution/durable-session-read.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{findSessionHookHolder}from"#execution/session-inbox/owner.js";import{EVE_PREWARM_ATTRIBUTE,EVE_SESSION_ATTRIBUTE,EVE_VERSION_ATTRIBUTE}from"#execution/eve-workflow-attributes.js";import{owningSandboxDefinition}from"#runtime/sandbox/registry.js";import{isRetiredSandboxSessionState,resolvePersistedSandboxSessionState}from"#sandbox/state.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";import{mapWithConcurrency}from"#shared/map-with-concurrency.js";import{isSessionStateIdleForHandoff}from"#execution/session/handoff-state.js";import{SESSION_HANDOFF_VERSION}from"#execution/session/entry-input.js";import{traceSessionHandover}from"#execution/session/handover-tracing.js";const log=createLogger(`execution.handoff`);async function startSuccessorStep(e){"use step";let{activationToken:t,anchorRunId:n,checkpoint:r,sessionWritable:i,targetDeploymentId:a,...o}=e,{capabilities:s}=await getWorld();if(s?.hookForceClaim!==!0||s.hookRetention?.active!==!0)return log.warn(`session handoff unavailable: the Workflow world cannot force-claim hooks`,{sessionId:n}),{kind:`unsupported`};if(!isSessionStateIdleForHandoff(r))return{kind:`not-idle`};let c={...o,activationToken:t,checkpoint:r,handoffVersion:SESSION_HANDOFF_VERSION,kind:`handoff`,ownerDeploymentId:a,sessionWritable:i,sessionId:n};return{kind:`started`,runId:(await startWorkflowOnDeployment(workflowEntryReference,[c],a,r.retention===void 0?void 0:{experimental_retention:r.retention})).runId}}async function hasRunEndedStep(e){"use step";return await hasRunEnded(e.runId)}async function prepareSuccessorStep(e){"use step";let{migration:t}=e,unreadable=t=>(log.warn(`session handoff refused: this deployment cannot read the checkpoint`,{detail:t,readableCheckpointVersion:SESSION_CHECKPOINT_VERSION,sessionId:e.sessionId}),{kind:`incompatible`,reason:`checkpoint-version`});if(t.kind===`incompatible`)return unreadable(t.detail);let{checkpoint:n}=t,r=n.sessionTimeoutMs;if(r!==!1&&(typeof r!=`number`||!Number.isFinite(r)||r<0))throw Error(`Session checkpoint contains an invalid timeout duration.`);let i;try{i=await deserializeContext(n.serializedContext)}catch(e){if(e instanceof IncompatibleStateLayoutError)return unreadable(e.message);throw e}let a=i.require(BundleKey),o=readDurableSession(n.sessionState).sandboxState?.session;if(o!=null&&!isRetiredSandboxSessionState(o)){let e=owningSandboxDefinition(getResolvedRuntimeAgentNode(a.graph,a.nodeId).sandboxRegistry.sandbox);if(e.kind!==`independent`)throw Error(`Session checkpoint sandbox has no resolved provider.`);let t=getSandboxEnvironmentRuntime(e.environment),n=resolvePersistedSandboxSessionState(o,t);if(n?.providerName!==t.providerName||n.stateProtocolVersion!==t.stateProtocolVersion)throw Error(`Session checkpoint sandbox provider state is incompatible.`)}if(!isSessionStateIdleForHandoff(n))throw Error(`Session checkpoint contains pending work and cannot be handed off.`);return e.source!==void 0&&!await holdsEveryAddress(e.source)?{kind:`source-gone`}:(await recordSessionOwner(e.sessionId),(e.handoffVersion??1)<SESSION_HANDOFF_VERSION&&log.info(`session moved from an owner that releases its addresses first`,{handoffVersion:e.handoffVersion??1,sessionId:e.sessionId}),{kind:`valid`})}async function holdsEveryAddress(e){return(await mapWithConcurrency(e.hookTokens,16,e=>findSessionHookHolder(sessionInboxHookToken(e)))).every(t=>t?.runId===e.runId)}async function reportSessionHandoffRetainedStep(e){"use step";log.warn(`session handoff failed; the current owner keeps the session`,{...e,checkpointVersion:SESSION_CHECKPOINT_VERSION})}async function recordSessionOwnerStep(e){"use step";await recordSessionOwner(e.sessionId)}async function recordSessionOwner(e){let{setAttributes:t}=await import(`#compiled/@workflow/core/index.js`);await t({[EVE_SESSION_ATTRIBUTE]:e,[EVE_PREWARM_ATTRIBUTE]:`1`,[EVE_VERSION_ATTRIBUTE]:resolveInstalledPackageInfo().version},{allowReservedAttributes:!0})}async function signalSessionOwnerActivationStep(e){"use step";try{await resumeHook(e.token,e.activation)}catch(e){if(!HookNotFoundError.is(e))throw e}}async function reportSessionTakenOverOutsideAttemptStep(e){"use step";log.error(`session taken over with no handoff attempt open; this run leaves without finalizing`,{sessionId:e.sessionId})}async function reportHandoverPartStuckStep(e){"use step";log.warn(`session handover part keeps failing; the previous owner keeps retrying`,e)}async function sendSessionHandoverPartStep(e){"use step";let t={"eve.handoff.buffered_payload_count":e.bufferedPayloadCount,"eve.handoff.part_index":e.part.index};e.part.index===0&&traceSessionHandover(`forwarding_started`,e.sessionId,e.part.attemptKey,t);try{let n=await resumeHook(sessionInboxHookToken(sessionCommandHookToken(e.sessionId)),{...e.part,kind:`handover`});return traceSessionHandover(e.part.final===!0?`final_submitted`:`part_submitted`,e.sessionId,e.part.attemptKey,{...t,"eve.handoff.destination_run_id":n.runId}),`delivered`}catch(e){if(HookNotFoundError.is(e))return`session-ended`;throw e}}async function signalSessionAnchorStep(e){"use step";await resumeHook(e.token,e.result)}export{hasRunEndedStep,prepareSuccessorStep,recordSessionOwnerStep,reportHandoverPartStuckStep,reportSessionHandoffRetainedStep,reportSessionTakenOverOutsideAttemptStep,sendSessionHandoverPartStep,signalSessionAnchorStep,signalSessionOwnerActivationStep,startSuccessorStep};
1
+ import{createLogger}from"#internal/logging.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{getSandboxEnvironmentRuntime}from"#shared/sandbox-environment.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{getWorld,resumeHook}from"#internal/workflow/runtime.js";import{hasRunEnded,startWorkflowOnDeployment,workflowEntryReference}from"#execution/workflow-runtime.js";import{readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{getResolvedRuntimeAgentNode}from"#runtime/graph.js";import{IncompatibleStateLayoutError,deserializeContext}from"#context/serialize.js";import{readDurableSession}from"#execution/durable-session-read.js";import{HookNotFoundError}from"#compiled/@workflow/errors/index.js";import{findSessionHookHolder}from"#execution/session-inbox/owner.js";import{EVE_PREWARM_ATTRIBUTE,EVE_SESSION_ATTRIBUTE,EVE_VERSION_ATTRIBUTE}from"#execution/eve-workflow-attributes.js";import{owningSandboxDefinition}from"#runtime/sandbox/registry.js";import{isRetiredSandboxSessionState,resolvePersistedSandboxSessionState}from"#sandbox/state.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";import{mapWithConcurrency}from"#shared/map-with-concurrency.js";import{isSessionStateIdleForHandoff}from"#execution/session/handoff-state.js";import{SESSION_HANDOFF_VERSION}from"#execution/session/entry-input.js";import{traceSessionHandover}from"#execution/session/handover-tracing.js";const log=createLogger(`execution.handoff`);async function startSuccessorStep(e){"use step";let{activationToken:t,anchorRunId:n,checkpoint:r,sessionWritable:i,targetDeploymentId:a,...o}=e,{capabilities:s}=await getWorld();if(s?.hookForceClaim!==!0||s.hookRetention?.active!==!0)return log.warn(`session handoff unavailable: the Workflow world cannot force-claim hooks`,{sessionId:n}),{kind:`unsupported`};if(!isSessionStateIdleForHandoff(r))return{kind:`not-idle`};let c={...o,activationToken:t,checkpoint:r,handoffVersion:SESSION_HANDOFF_VERSION,kind:`handoff`,ownerDeploymentId:a,sessionWritable:i,sessionId:n};return{kind:`started`,runId:(await startWorkflowOnDeployment(workflowEntryReference,[c],a,r.retention===void 0?void 0:{experimental_retention:r.retention})).runId}}async function hasRunEndedStep(e){"use step";return await hasRunEnded(e.runId)}async function prepareSuccessorStep(e){"use step";let{migration:t}=e,unreadable=t=>(log.warn(`session handoff refused: this deployment cannot read the checkpoint`,{detail:t,readableCheckpointVersion:SESSION_CHECKPOINT_VERSION,sessionId:e.sessionId}),{kind:`incompatible`,reason:`checkpoint-version`});if(t.kind===`incompatible`)return unreadable(t.detail);let refuse=e=>{if(t.kind===`pre-v27`)return unreadable(e);throw Error(e)},n=t.kind===`pre-v27`?t.imported.checkpoint:t.checkpoint,r=n.sessionTimeoutMs;if(r!==!1&&(typeof r!=`number`||!Number.isFinite(r)||r<0))return refuse(`Session checkpoint contains an invalid timeout duration.`);let i;try{i=await deserializeContext(n.serializedContext)}catch(e){if(e instanceof IncompatibleStateLayoutError)return unreadable(e.message);throw e}let a=i.require(BundleKey),o=readDurableSession(n.sessionState).sandboxState?.session;if(o!=null&&!isRetiredSandboxSessionState(o)){let e=owningSandboxDefinition(getResolvedRuntimeAgentNode(a.graph,a.nodeId).sandboxRegistry.sandbox);if(e.kind!==`independent`)return refuse(`Session checkpoint sandbox has no resolved provider.`);let t=getSandboxEnvironmentRuntime(e.environment),n=resolvePersistedSandboxSessionState(o,t);if(n?.providerName!==t.providerName||n.stateProtocolVersion!==t.stateProtocolVersion)return refuse(`Session checkpoint sandbox provider state is incompatible.`)}return isSessionStateIdleForHandoff(n)?e.source!==void 0&&!await holdsEveryAddress(e.source)?{kind:`source-gone`}:(await recordSessionOwner(e.sessionId),(e.handoffVersion??1)<SESSION_HANDOFF_VERSION&&log.info(`session moved from an owner that releases its addresses first`,{handoffVersion:e.handoffVersion??1,sessionId:e.sessionId}),t.kind===`pre-v27`&&log.info(`session handoff accepted from an owner before v27`,{sessionId:e.sessionId}),{kind:`valid`}):refuse(`Session checkpoint contains pending work and cannot be handed off.`)}async function holdsEveryAddress(e){return(await mapWithConcurrency(e.hookTokens,16,e=>findSessionHookHolder(sessionInboxHookToken(e)))).every(t=>t?.runId===e.runId)}async function reportSessionHandoffRetainedStep(e){"use step";log.warn(`session handoff failed; the current owner keeps the session`,{...e,checkpointVersion:SESSION_CHECKPOINT_VERSION})}async function recordSessionOwnerStep(e){"use step";await recordSessionOwner(e.sessionId)}async function recordSessionOwner(e){let{setAttributes:t}=await import(`#compiled/@workflow/core/index.js`);await t({[EVE_SESSION_ATTRIBUTE]:e,[EVE_PREWARM_ATTRIBUTE]:`1`,[EVE_VERSION_ATTRIBUTE]:resolveInstalledPackageInfo().version},{allowReservedAttributes:!0})}async function signalSessionOwnerActivationStep(e){"use step";try{await resumeHook(e.token,e.activation)}catch(e){if(!HookNotFoundError.is(e))throw e}}async function reportSessionTakenOverOutsideAttemptStep(e){"use step";log.error(`session taken over with no handoff attempt open; this run leaves without finalizing`,{sessionId:e.sessionId})}async function reportHandoverPartStuckStep(e){"use step";log.warn(`session handover part keeps failing; the previous owner keeps retrying`,e)}async function sendSessionHandoverPartStep(e){"use step";let t={"eve.handoff.buffered_payload_count":e.bufferedPayloadCount,"eve.handoff.part_index":e.part.index};e.part.index===0&&traceSessionHandover(`forwarding_started`,e.sessionId,e.part.attemptKey,t);try{let n=await resumeHook(sessionInboxHookToken(sessionCommandHookToken(e.sessionId)),{...e.part,kind:`handover`});return traceSessionHandover(e.part.final===!0?`final_submitted`:`part_submitted`,e.sessionId,e.part.attemptKey,{...t,"eve.handoff.destination_run_id":n.runId}),`delivered`}catch(e){if(HookNotFoundError.is(e))return`session-ended`;throw e}}async function signalSessionAnchorStep(e){"use step";await resumeHook(e.token,e.result)}async function readSessionStreamTailStep(e){"use step";return await readSessionStreamTailIndex(e.sessionId)}export{hasRunEndedStep,prepareSuccessorStep,readSessionStreamTailStep,recordSessionOwnerStep,reportHandoverPartStuckStep,reportSessionHandoffRetainedStep,reportSessionTakenOverOutsideAttemptStep,sendSessionHandoverPartStep,signalSessionAnchorStep,signalSessionOwnerActivationStep,startSuccessorStep};
@@ -0,0 +1,2 @@
1
+ import type { ModelMessage } from "ai";
2
+ export declare function normalizeHistory(messages: readonly ModelMessage[]): import("#harness/messages.js").HarnessModelMessage[];
@@ -0,0 +1 @@
1
+ import{isUserMessageKind,validateHarnessModelMessages}from"#harness/messages.js";function normalizeHistory(e){let t=[],n=new Map,settle=()=>{n.size!==0&&(t.push({role:`tool`,content:[...n].map(([e,t])=>({type:`tool-result`,toolCallId:e,toolName:t,output:{type:`error-text`,value:`Interrupted by the session upgrade. Start this work again if it is still needed.`}}))}),n.clear())};for(let r of e){let e=r;if(e.role===`assistant`&&Array.isArray(e.content))e={...e,content:e.content.filter(e=>e.type!==`tool-approval-request`)};else if(e.role===`tool`&&(e={...e,content:e.content.filter(e=>e.type!==`tool-approval-response`)},e.content.length===0))continue;if(e.role!==`tool`&&settle(),e.role===`assistant`&&Array.isArray(e.content))for(let t of e.content)t.type===`tool-call`&&n.set(t.toolCallId,t.toolName);if(e.role===`tool`)for(let t of e.content)t.type===`tool-result`&&n.delete(t.toolCallId);let i=e.kind;t.push(e.role===`user`&&!isUserMessageKind(i)?{...e,kind:`user`}:e)}return settle(),validateHarnessModelMessages(t)}export{normalizeHistory};
@@ -1,3 +1,3 @@
1
- import{createErrorId,createLogger}from"#internal/logging.js";import{eventsOfLine}from"#protocol/session-lines.js";import{currentProjection,saveSessionProjection}from"#harness/session-machine/current.js";import{rowOf}from"#protocol/session-projection/tree.js";import{serializeContext}from"#context/serialize.js";import{createImportedHistoryMessages}from"#harness/messages.js";import{applyTransition,dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{fail,receive,stopInterruptedSteps}from"#harness/session-machine/transitions.js";import{controlAdmitted,fact}from"#harness/facts.js";import{activeTurnIdOf}from"#protocol/session-projection.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{supersede}from"#harness/session-machine/cascade.js";import{preserveStoppedTurnMessage}from"#execution/cancelled-model-call-batch.js";import{resolveSessionStepResult}from"#execution/session/turn-step-result.js";import{interruptedAttemptNote}from"#harness/interrupted-attempt.js";import{replaceSessionHistory}from"#harness/compaction/step.js";import{summarizeFailure}from"#execution/failure-summary.js";const log=createLogger(`execution.interrupted-step`);function readInterruptedAttempt(e,t){let n=new Map,r=new Map,i=new Set,a,o=!1,s,call=e=>{let t=n.get(e);return t===void 0&&n.set(e,t={name:``,started:!1}),t};for(let{line:e,position:n}of t)if(`facts`in e)for(let t of eventsOfLine(e,n,e.at))switch(t.type){case`call.requested`:Object.assign(call(t.data.callId),{input:t.data.input,name:t.data.capability.name});break;case`call.started`:call(t.data.callId).started=!0;break;case`call.settled`:call(t.data.callId).outcome=t.data.outcome;break;case`interaction.settled`:i.add(t.data.interactionId);break;case`content.completed`:t.data.kind===`text`&&typeof t.data.value==`string`&&r.set(t.data.partId,t.data.value);break;case`turn.settled`:{let e=(t.data.reply??[]).flatMap(e=>r.get(e)??[]);s={failed:t.data.outcome===`failed`,...e.length>0&&{text:e.join(`
1
+ import{createErrorId,createLogger}from"#internal/logging.js";import{eventsOfLine}from"#protocol/session-lines.js";import{currentProjection,saveSessionProjection}from"#harness/session-machine/current.js";import{rowOf}from"#protocol/session-projection/tree.js";import{serializeContext}from"#context/serialize.js";import{createImportedHistoryMessages}from"#harness/messages.js";import{applyTransition,dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{fail,receive,stopInterruptedSteps}from"#harness/session-machine/transitions.js";import{activeTurnIdOf}from"#protocol/session-projection.js";import{controlAdmitted,fact}from"#harness/facts.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{supersede}from"#harness/session-machine/cascade.js";import{preserveStoppedTurnMessage}from"#execution/cancelled-model-call-batch.js";import{resolveSessionStepResult}from"#execution/session/turn-step-result.js";import{interruptedAttemptNote}from"#harness/interrupted-attempt.js";import{replaceSessionHistory}from"#harness/compaction/step.js";import{summarizeFailure}from"#execution/failure-summary.js";const log=createLogger(`execution.interrupted-step`);function readInterruptedAttempt(e,t){let n=new Map,r=new Map,i=new Set,a,o=!1,s,call=e=>{let t=n.get(e);return t===void 0&&n.set(e,t={name:``,started:!1}),t};for(let{line:e,position:n}of t)if(`facts`in e)for(let t of eventsOfLine(e,n,e.at))switch(t.type){case`call.requested`:Object.assign(call(t.data.callId),{input:t.data.input,name:t.data.capability.name});break;case`call.started`:call(t.data.callId).started=!0;break;case`call.settled`:call(t.data.callId).outcome=t.data.outcome;break;case`interaction.settled`:i.add(t.data.interactionId);break;case`content.completed`:t.data.kind===`text`&&typeof t.data.value==`string`&&r.set(t.data.partId,t.data.value);break;case`turn.settled`:{let e=(t.data.reply??[]).flatMap(e=>r.get(e)??[]);s={failed:t.data.outcome===`failed`,...e.length>0&&{text:e.join(`
2
2
 
3
3
  `)}};break}case`session.ended`:a=t.data.outcome;break;case`context.settled`:t.data.kind===`clear`&&t.data.outcome===`completed`&&(o=!0)}return{calls:n,cleared:o,sessionEnded:a,settledInteractions:i,settledTurn:s,since:e}}async function recoverInterruptedStep(e){let{attempt:t,ctx:n}=e,r=e.session,publish=async t=>{r=await e.publish(t,r)},view=()=>sessionView(currentProjection(n),r.state),closeAttempt=async e=>{let t=currentProjection(n).view,r=supersede(t,n=>{let r=rowOf(t,n.family,n.id);return r!==void 0&&e(n,r)},`step-interrupted`);r.length>0&&await publish(r)},introduced=e=>e.introducedAt>=t.since,finish=e=>{let t=saveSessionProjection(dropClosedRecords(reconcileSessionContinuationToken(n,e.session),currentProjection(n)),n);return{result:resolveSessionStepResult({...e,session:t},serializeContext(n))}};if(t.sessionEnded!==void 0)return finish({next:{done:!0,isError:t.sessionEnded===`failed`,output:t.settledTurn?.text??``},session:r});if(e.control!==void 0){if(await closeAttempt(({family:e},t)=>(e===`run`||e===`change`)&&introduced(t)),t.cleared){let e=saveTransition(r,{clearsHistory:!0,events:[],signIns:[],turn:{remembered:view().turn.remembered,suspended:[]}});r=replaceSessionHistory(e,[])}let{delivery:i,kind:a}=e.control,o=i===void 0?void 0:currentProjection(n).view.deliveries[i.deliveryId]?.status;return i!==void 0&&o!==`settled`&&await publish([...o===void 0?[controlAdmitted(i,a)]:[],fact(`delivery.settled`,{deliveryId:i.deliveryId,outcome:`failed`,reason:`${a}-interrupted`})]),finish({next:null,session:r})}let{settledTurn:i}=t;if(i!==void 0&&activeTurnIdOf(currentProjection(n))===void 0)return r={...r,history:[...r.history,...createImportedHistoryMessages(e.stepInput?.history??[])]},r=await preserveStoppedTurnMessage(n,r,e.stepInput),i.text!==void 0&&(r={...r,history:[...r.history,{content:i.text,role:`assistant`}]}),finish({next:null,session:r,settledTurn:{isError:i.failed,output:i.text??``}});let a=stopInterruptedSteps(view(),t),o=new Set(view().turn.suspended.filter(e=>!a.turn.suspended.includes(e)).flatMap(e=>e.requests.map(e=>e.interactionId)));await closeAttempt(({family:e,id:n},r)=>{switch(e){case`run`:case`change`:return introduced(r);case`call`:return r.taskId===void 0&&(introduced(r)||t.calls.get(n)?.started===!0);case`interaction`:return!view().relayedRequestIds.has(n)&&(introduced(r)||o.has(n));default:return!1}});let s=activeTurnIdOf(currentProjection(n)),c=s===void 0?0:turnInterruptions(r.state,s)+1;r=saveTransition(r,a);let l=interruptedAttemptNote(t.calls);if(l!==void 0&&(r={...r,history:[...r.history,l]}),e.failed===void 0&&c<=3){let{settledInteractions:n}=t,i=e.stepInput?.answers?.filter(e=>!n.has(e.interactionId));return{session:s===void 0?r:withTurnInterruptions(r,s,c),stepInput:e.stepInput===void 0?void 0:{...e.stepInput,answers:i}}}e.admission.length>0&&await publish(e.admission);let u=(e.stepInput?.deliveries??[]).filter(({deliveryId:e})=>currentProjection(n).view.deliveries[e]?.status===`admitted`);u.length>0&&await publish(receive(view(),{deliveries:u}).events);let d=activeTurnIdOf(currentProjection(n));if(d===void 0)return finish({next:null,session:r});r=await preserveStoppedTurnMessage(n,r,e.stepInput);let f=e.failed===void 0?{code:`STEP_INTERRUPTED`,details:{errorId:createErrorId()},message:`This turn was interrupted too many times to continue.`}:summarizeFailure(e.failed.error,`STEP_FAILED`);return log.error(`turn failed`,{code:f.code,errorId:f.details.errorId,sessionId:r.sessionId,turnId:d}),r=await applyTransition(r,fail(view(),f),publish),finish({next:null,session:r,settledTurn:{isError:!0,output:f.message}})}const INTERRUPTIONS_STATE_KEY=`eve.turn-interruptions`,MAX_TURN_INTERRUPTIONS=3;function turnInterruptions(e,t){let n=e?.[INTERRUPTIONS_STATE_KEY];return n?.turnId===t?n.count:0}function withTurnInterruptions(e,t,n){return{...e,state:{...e.state,[INTERRUPTIONS_STATE_KEY]:{count:n,turnId:t}}}}export{MAX_TURN_INTERRUPTIONS,readInterruptedAttempt,recoverInterruptedStep};
@@ -0,0 +1,36 @@
1
+ import { type SessionCheckpoint } from "#execution/session/handoff.js";
2
+ import { type SessionProjection } from "#protocol/session-projection.js";
3
+ export interface PreV27Checkpoint<C = SessionCheckpoint> {
4
+ /** The checkpoint in v27's shape, without its session projection. */
5
+ readonly checkpoint: C;
6
+ /** Turns the earlier owner numbered: the next turn takes the next number. */
7
+ readonly turnCount: number;
8
+ }
9
+ export type PreV27CheckpointImport =
10
+ /** Its checkpoint still unchecked against the current shape. */
11
+ {
12
+ readonly kind: "pre-v27";
13
+ readonly imported: PreV27Checkpoint<Record<string, unknown>>;
14
+ }
15
+ /** Work the earlier owner runs will finish; a later delivery can move the session. */
16
+ | {
17
+ readonly kind: "busy";
18
+ readonly detail: string;
19
+ } | {
20
+ readonly kind: "incompatible";
21
+ readonly detail: string;
22
+ };
23
+ export declare function isPreV27CheckpointVersion(version: unknown): version is number;
24
+ /**
25
+ * Reads a pre-v27 checkpoint in v27's shape. Pure, so the session workflow can run it before
26
+ * validation. The earlier owner only hands off an idle session; a task it still tracks keeps the
27
+ * session on that owner.
28
+ */
29
+ export declare function importPreV27Checkpoint(checkpoint: Readonly<Record<string, unknown>>): PreV27CheckpointImport;
30
+ /**
31
+ * The projection of a session whose earlier lines a v27 writer never folded: it writes after
32
+ * `tailIndex`, and its next turn follows the earlier owner's last. An empty stream has not opened.
33
+ */
34
+ export declare function preV27Projection(tailIndex: number, turnCount: number): SessionProjection;
35
+ /** The imported checkpoint with its session projection. */
36
+ export declare function withProjection(checkpoint: SessionCheckpoint, projection: SessionProjection): SessionCheckpoint;
@@ -0,0 +1 @@
1
+ import{isObject}from"#shared/guards.js";import{EARLIER_REMOTE_CALLER_CONTEXT_KEY_NAME,SESSION_CALLBACK_CONTEXT_KEY_NAME}from"#context/key-names.js";import{SESSION_PROJECTION_STATE_KEY}from"#harness/session-machine/view.js";import{DURABLE_SESSION_VERSION}from"#execution/durable-session-read.js";import{initialSessionProjection}from"#protocol/session-projection.js";import{normalizeHistory}from"#execution/session/imported-conversation.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";import{CheckpointRefusal,refuse}from"#execution/session/checkpoint-refusal.js";function isPreV27CheckpointVersion(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>=10&&e<=17}function importPreV27Checkpoint(e){try{return{kind:`pre-v27`,imported:importCheckpoint(e)}}catch(t){if(!(t instanceof CheckpointRefusal)&&!(t instanceof SessionBusy))throw t;return{kind:t instanceof SessionBusy?`busy`:`incompatible`,detail:`checkpoint version ${String(e.version)}: ${t.message}`}}}function preV27Projection(e,t){let n=initialSessionProjection();return{...n,view:{...n.view,position:e+1,session:{status:e<0?`new`:`open`,turnCount:t,...t>0&&{latestTurnId:`turn_${String(t-1)}`}}}}}function withProjection(e,t){let{sessionState:n}=e,{session:r}=n.snapshot;return{...e,sessionState:{...n,snapshot:{...n.snapshot,session:{...r,state:{...r.state,[SESSION_PROJECTION_STATE_KEY]:t}}}}}}function importCheckpoint(e){let t=readRecord(e,`sessionState`),n=readRecord(readRecord(t,`snapshot`),`session`);typeof t.sessionId!=`string`&&refuse(`session id is missing`);let r=n.state===void 0?{}:readRecord(n,`state`),i=readTurnCount(t,r);if(holdsRunningTask(r[`eve.taskTable`]))throw new SessionBusy(`session holds a running task`);let a=Array.isArray(e.history)?e.history:n.history;Array.isArray(a)||refuse(`session history is missing`);let o=readRecord(e,`serializedContext`),s=o[SESSION_CALLBACK_CONTEXT_KEY_NAME],c=isObject(s)?o[`eve.legacyRemoteAgentCaller`]===void 0?2:1:void 0;return{checkpoint:{admittedDeliveryKeys:Array.isArray(e.admittedDeliveryKeys)?e.admittedDeliveryKeys:[],...c===void 0?e.capabilities!==void 0&&{capabilities:e.capabilities}:{capabilities:{requestInput:!1}},history:importHistory(a),...e.retention!==void 0&&{retention:e.retention},serializedContext:c===void 0?o:{...o,"eve.capabilities":{requestInput:!1},[EARLIER_REMOTE_CALLER_CONTEXT_KEY_NAME]:c},sessionState:{continuationToken:t.continuationToken,hasProxyInputRequests:!1,sessionId:t.sessionId,snapshot:{session:{agent:isObject(n.agent)?n.agent:{system:``},continuationToken:n.continuationToken,sessionId:n.sessionId,...pick(n,[`outputSchema`,`rootSessionId`,`sandboxState`]),state:Object.fromEntries(Object.entries(r).filter(([e])=>!e.startsWith(`eve.`)))}},version:DURABLE_SESSION_VERSION},sessionTimeoutMs:e.sessionTimeoutMs,version:SESSION_CHECKPOINT_VERSION},turnCount:i}}function readTurnCount(e,t){let n=t[SESSION_PROJECTION_STATE_KEY];if(isObject(n))return n.activeTurnId!==void 0&&refuse(`a turn is still open`),readCount(n.nextSequence);let r=t[`eve.harness.emission`]??e.emissionState;return isObject(r)||refuse(`the session's turn position is missing`),r.turnId!==``&&refuse(`a turn is still open`),readCount(r.sequence)}function readCount(e){return(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)&&refuse(`the session's turn position is malformed`),e}function holdsRunningTask(e){return e!==void 0&&((!isObject(e)||!Array.isArray(e.tasks))&&refuse(`task table is malformed`),e.tasks.some(e=>!isObject(e)||e.run!==void 0||Array.isArray(e.held)&&e.held.length>0||Array.isArray(e.calls)&&e.calls.length>0))}var SessionBusy=class extends Error{};function importHistory(e){try{return normalizeHistory(e)}catch(e){refuse(`session history is malformed: ${e instanceof Error?e.message:`unknown`}`)}}function pick(e,t){return Object.fromEntries(t.flatMap(t=>e[t]===void 0?[]:[[t,e[t]]]))}function readRecord(e,t){let n=e[t];return isObject(n)||refuse(`${t} is not an object`),n}export{importPreV27Checkpoint,isPreV27CheckpointVersion,preV27Projection,withProjection};
@@ -41,6 +41,8 @@ export interface SessionBoot {
41
41
  readonly anchor: SessionAnchor;
42
42
  readonly caller: TurnCaller | undefined;
43
43
  readonly capabilities?: SessionCapabilities;
44
+ /** Compacts the history before the first action, for a session an earlier build recorded. */
45
+ readonly compactFirst?: boolean;
44
46
  readonly deploymentId: string;
45
47
  readonly history: HarnessModelMessage[];
46
48
  readonly initialTurnControl?: TurnControl;
@@ -1 +1 @@
1
- import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{storedProjection}from"#harness/session-machine/view.js";import{workingTasks}from"#execution/tasks/table.js";import{settleCancelledTurnStep}from"#execution/settle-cancelled-turn-step.js";import{turnCoordinates}from"#protocol/session-projection.js";import"#execution/session-inbox/inbox.js";import{signalSessionAnchorStep}from"#execution/session/handoff-steps.js";import{controlDeliveryOf}from"#execution/session/control-delivery.js";import{settleControlDeliveryStep}from"#execution/session/settle-control-delivery-step.js";import{SessionInputQueue}from"#execution/session/input-queue.js";import{createTurnControl}from"#execution/session/turn-control.js";import{SessionHandoff,sessionAnchorToken}from"#execution/session/handoff.js";import{notifyCancelledTaskCallerStep,notifyTurnCallerStep,resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{withStubPlayback}from"#execution/tool-stubs/playback.js";import{nextTurnDelivery}from"#execution/session/next-input.js";import{SessionExecution}from"#execution/session/turn.js";import{SessionStateCursor}from"#execution/session/state-cursor.js";import{cancelWorkingTasks,sessionTaskTable}from"#execution/tasks/session.js";import{finalizeSession}from"#execution/session/finalization.js";import{prewarmSessionStep}from"#execution/session/prewarm-step.js";function createSafeOuterWorkflowError(){let e=Error(`Agent workflow failed. Inspect the private session trace for details.`);return e.name=`EveWorkflowFailure`,e}async function runPreparedSession(e,t){let n=e.serializedContext[STUB_CONTEXT_KEY];n!==void 0&&n.rootSessionId===void 0&&(e.serializedContext[STUB_CONTEXT_KEY]={...n,rootSessionId:e.sessionId});let r=new SessionStateCursor({history:e.history,inbox:t,sessionWritable:e.sessionWritable,serializedContext:e.serializedContext,sessionState:e.sessionState}),i={caller:e.caller},a=new SessionHandoff({checkpoint:{capabilities:e.capabilities,retention:e.retention,sessionTimeoutMs:e.sessionTimeoutMs},deploymentId:e.deploymentId,inbox:t,isInitialOwner:e.anchor.kind===`self`,sessionId:e.sessionId,sessionWritable:e.sessionWritable}),o={output:``,isError:!0},s,c=!1;try{return o=await withStubPlayback(n,e.sessionId,async()=>{try{s=await runSessionLoop(e,{cursor:r,handoff:a,inbox:t,progress:i})}finally{await t.dispose()}return s.kind===`transferred`?e.anchor.kind===`self`?(o=await a.awaitAnchoredResult(),o):{output:``}:(c=!0,o=await finalizeSession(s.outcome,{caller:i.caller,cursor:r,sessionWritable:e.sessionWritable}),o)}),o}catch(t){throw c||await finalizeSession({error:t,kind:`failed`,turnId:i.turnId},{caller:i.caller,cursor:r,sessionWritable:e.sessionWritable}),createSafeOuterWorkflowError()}finally{await t.dispose(),await reportResultToAnchor(e,o,a,s)}}async function failSession(e){let t;try{t=await resolveInitialTurnCallerStep({serializedContext:e.serializedContext})}catch{}throw await finalizeSession({error:e.error,kind:`failed`},{caller:t,cursor:{serializedContext:e.serializedContext,sessionState:e.sessionState},sessionWritable:e.sessionWritable}),createSafeOuterWorkflowError()}async function reportResultToAnchor(e,t,n,r){switch(e.anchor.kind){case`self`:await n.disposeAnchor(),await e.anchor.notify?.(t);return;case`successor`:if(r?.kind===`transferred`)return;await signalSessionAnchorStep({result:t,token:sessionAnchorToken(e.sessionId)});return}}async function runSessionLoop(e,t){let{cursor:n,handoff:r,inbox:i,progress:a}=t,o=new SessionInputQueue(e.admittedDeliveryKeys),s=new SessionExecution({capabilities:e.capabilities,cursor:n,inbox:i,queue:o,sessionId:e.sessionId}),c=e.sessionTimeoutControl,l=Promise.resolve(),u=!0,d=!1,f=[],started=()=>storedProjection(n.sessionState.snapshot.session.state).view.session.status!==`new`,ignore=async e=>{if(!started()){f.push(e);return}await n.advance(t=>settleControlDeliveryStep({...t,settlement:e}))},settleUnstarted=async()=>{if(started())for(let e of f.splice(0))await n.advance(t=>settleControlDeliveryStep({...t,settlement:e}))},expired=e=>({kind:`expired`,...e&&{control:e},...f.length>0&&{settles:f.splice(0)}}),nextParkedActivity=async()=>{for(;;){let e=await nextTurnDelivery({cursor:n,hasWorkingTasks:()=>workingTasks(sessionTaskTable(n)).length>0,ignore,inbox:i,queue:o});if(e.kind===`prewarm`){if(u&&a.caller===void 0&&workingTasks(sessionTaskTable(n)).length===0&&o.pendingCount===0&&!i.hasPending()){let t=c?.getDeadline(),n=await r.tryPrewarmTransfer(transferState(),e.targetDeploymentId,t);if(n.kind===`transferred`)return n}continue}if(e.kind===`workflow`){await s.handleWorkflowMessage(e.message);continue}if(e.kind===`cancel-working-tasks`){if(await cancelWorkingTasks(n,`turn-cancelled`),e.origin!==void 0){let t=controlDeliveryOf(e.origin);await n.advance(e=>settleControlDeliveryStep({...e,settlement:{control:t,outcome:`applied`,source:`cancel`}}))}continue}if(!(e.kind===`expired`&&c!==void 0&&((o.pendingCount>0||i.hasPending())&&c.recordActivity(),await c.handleTimerElapsed()===`extended`)))return e}},p=e.initialTurnControl??(e.anchor.kind===`self`?createTurnControl():void 0),m=!1,runTurn=async e=>{let t=a.caller,r=p;p=void 0,a.turnId=e?.control===void 0?turnCoordinates(storedProjection(n.sessionState.snapshot.session.state)).turnId:void 0;let i=await s.runTurn(e,{caller:t,control:r});return a.turnId=void 0,c?.recordActivity(),i.caller!==void 0&&(a.caller=i.caller),i.compacted===!0&&(m=!0),i},transferState=()=>({admittedDeliveryKeys:o.admittedDeliveryKeys,history:n.history,serializedContext:n.serializedContext,sessionState:n.sessionState}),compactionHandoffReady=()=>m&&a.caller===void 0&&workingTasks(sessionTaskTable(n)).length===0,tryCompactionHandoff=async()=>{if(!compactionHandoffReady()||o.pendingCount>0||i.hasPending())return;let e=await r.tryCompactionTransfer(transferState());return e.kind===`transferred`?e:void 0},runDeliveredTurn=async e=>{let t=await r.tryTransfer(e,transferState());return t.kind===`transferred`?t:(e.delivery.caller!==void 0&&(a.caller=e.delivery.caller),{action:await runTurn({delivery:e.delivery}),kind:`action`})},settleCancelledTurn=async(e,t)=>{let r=await n.advanceWithHistory(n=>settleCancelledTurnStep({...n,control:t,reportUsage:e}));return a.caller=void 0,r},awaitPrewarmedAction=async()=>{for(;;){let e=await nextParkedActivity();switch(d=!1,e.kind){case`reset`:return{kind:`terminal`,outcome:expired(e.origin&&controlDeliveryOf(e.origin))};case`closed`:return i.takenOver?await r.adoptTakeover():{kind:`terminal`,outcome:expired()};case`transferred`:return e;case`expired`:return{kind:`terminal`,outcome:expired()};case`clear`:case`compact`:e.origin!==void 0&&await ignore({control:controlDeliveryOf(e.origin),outcome:`ignored`,source:e.kind});continue;case`turn`:return await runDeliveredTurn(e);case`cancel-turn`:continue}}},runInitialAction=async()=>{switch(e.start.kind){case`first-message`:return d=!0,u=!1,l=n.advanceBeside(({serializedContext:e,sessionState:t})=>prewarmSessionStep({serializedContext:e,sessionState:t}),()=>d).then(()=>void 0,()=>void 0).finally(()=>{u=!0}),await awaitPrewarmedAction();case`parked`:return{action:{kind:`park`},kind:`action`};case`turn`:{let{input:t}=e.start;return{action:await runTurn(t===void 0?void 0:{delivery:t}),kind:`action`}}}};try{let[t,n]=await Promise.allSettled([runInitialAction(),c?.start()]);if(n.status===`rejected`)throw n.reason;if(t.status===`rejected`)throw t.reason;let o=t.value;if(o.kind!==`action`)return o;let l=o.action;for(;;){if(l.kind===`done`)return{kind:`terminal`,outcome:{action:l,kind:`done`}};if(await settleUnstarted(),l.cancelled===!0){let{caller:t}=a,n=await settleCancelledTurn(t!==void 0,l.cancelledBy);if(t!==void 0){let r={caller:t,sessionId:e.sessionId};await notifyCancelledTaskCallerStep(n.usage===void 0?r:{...r,usage:n.usage})}}else l.settled!==void 0&&(a.caller!==void 0&&await notifyTurnCallerStep({caller:a.caller,lifecycle:`parked`,sessionId:e.sessionId,settled:l.settled}),a.caller=void 0);let t=await tryCompactionHandoff();if(t!==void 0)return t;p??=createTurnControl();let n=await nextParkedActivity();switch(n.kind){case`reset`:return{kind:`terminal`,outcome:resetOutcome(n.origin)};case`closed`:return i.takenOver?await r.adoptTakeover():{kind:`terminal`,outcome:{kind:`expired`}};case`transferred`:return n;case`expired`:return{kind:`terminal`,outcome:{kind:`expired`}};case`clear`:case`compact`:l=await runTurn(n.origin===void 0?{control:n.kind}:{control:n.kind,controlDelivery:controlDeliveryOf(n.origin)});continue;case`cancel-turn`:await s.cancelTurnWork(),await settleCancelledTurn(!1,n.origin===void 0?void 0:controlDeliveryOf(n.origin)),c?.recordActivity(),l={...l,settled:void 0};continue;case`turn`:{let e=await runDeliveredTurn(n);if(e.kind!==`action`)return e;l=e.action;continue}}}}finally{d=!1,await l,await c?.dispose()}}function resetOutcome(e){return e===void 0?{kind:`expired`}:{control:controlDeliveryOf(e),kind:`expired`}}export{failSession,runPreparedSession};
1
+ import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{storedProjection}from"#harness/session-machine/view.js";import{workingTasks}from"#execution/tasks/table.js";import{settleCancelledTurnStep}from"#execution/settle-cancelled-turn-step.js";import{turnCoordinates}from"#protocol/session-projection.js";import"#execution/session-inbox/inbox.js";import{signalSessionAnchorStep}from"#execution/session/handoff-steps.js";import{controlDeliveryOf}from"#execution/session/control-delivery.js";import{settleControlDeliveryStep}from"#execution/session/settle-control-delivery-step.js";import{SessionInputQueue}from"#execution/session/input-queue.js";import{createTurnControl}from"#execution/session/turn-control.js";import{SessionHandoff,sessionAnchorToken}from"#execution/session/handoff.js";import{notifyCancelledTaskCallerStep,notifyTurnCallerStep,resolveInitialTurnCallerStep}from"#subagents/parent-notification.js";import{withStubPlayback}from"#execution/tool-stubs/playback.js";import{nextTurnDelivery}from"#execution/session/next-input.js";import{SessionExecution}from"#execution/session/turn.js";import{SessionStateCursor}from"#execution/session/state-cursor.js";import{cancelWorkingTasks,sessionTaskTable}from"#execution/tasks/session.js";import{finalizeSession}from"#execution/session/finalization.js";import{prewarmSessionStep}from"#execution/session/prewarm-step.js";function createSafeOuterWorkflowError(){let e=Error(`Agent workflow failed. Inspect the private session trace for details.`);return e.name=`EveWorkflowFailure`,e}async function runPreparedSession(e,t){let n=e.serializedContext[STUB_CONTEXT_KEY];n!==void 0&&n.rootSessionId===void 0&&(e.serializedContext[STUB_CONTEXT_KEY]={...n,rootSessionId:e.sessionId});let r=new SessionStateCursor({history:e.history,inbox:t,sessionWritable:e.sessionWritable,serializedContext:e.serializedContext,sessionState:e.sessionState}),i={caller:e.caller},a=new SessionHandoff({checkpoint:{capabilities:e.capabilities,retention:e.retention,sessionTimeoutMs:e.sessionTimeoutMs},deploymentId:e.deploymentId,inbox:t,isInitialOwner:e.anchor.kind===`self`,sessionId:e.sessionId,sessionWritable:e.sessionWritable}),o={output:``,isError:!0},s,c=!1;try{return o=await withStubPlayback(n,e.sessionId,async()=>{try{s=await runSessionLoop(e,{cursor:r,handoff:a,inbox:t,progress:i})}finally{await t.dispose()}return s.kind===`transferred`?e.anchor.kind===`self`?(o=await a.awaitAnchoredResult(),o):{output:``}:(c=!0,o=await finalizeSession(s.outcome,{caller:i.caller,cursor:r,sessionWritable:e.sessionWritable}),o)}),o}catch(t){throw c||await finalizeSession({error:t,kind:`failed`,turnId:i.turnId},{caller:i.caller,cursor:r,sessionWritable:e.sessionWritable}),createSafeOuterWorkflowError()}finally{await t.dispose(),await reportResultToAnchor(e,o,a,s)}}async function failSession(e){let t;try{t=await resolveInitialTurnCallerStep({serializedContext:e.serializedContext})}catch{}throw await finalizeSession({error:e.error,kind:`failed`},{caller:t,cursor:{serializedContext:e.serializedContext,sessionState:e.sessionState},sessionWritable:e.sessionWritable}),createSafeOuterWorkflowError()}async function reportResultToAnchor(e,t,n,r){switch(e.anchor.kind){case`self`:await n.disposeAnchor(),await e.anchor.notify?.(t);return;case`successor`:if(r?.kind===`transferred`)return;await signalSessionAnchorStep({result:t,token:sessionAnchorToken(e.sessionId)});return}}async function runSessionLoop(e,t){let{cursor:n,handoff:r,inbox:i,progress:a}=t,o=new SessionInputQueue(e.admittedDeliveryKeys),s=new SessionExecution({capabilities:e.capabilities,cursor:n,inbox:i,queue:o,sessionId:e.sessionId}),c=e.sessionTimeoutControl,l=Promise.resolve(),u=!0,d=!1,f=[],started=()=>storedProjection(n.sessionState.snapshot.session.state).view.session.status!==`new`,ignore=async e=>{if(!started()){f.push(e);return}await n.advance(t=>settleControlDeliveryStep({...t,settlement:e}))},settleUnstarted=async()=>{if(started())for(let e of f.splice(0))await n.advance(t=>settleControlDeliveryStep({...t,settlement:e}))},expired=e=>({kind:`expired`,...e&&{control:e},...f.length>0&&{settles:f.splice(0)}}),nextParkedActivity=async()=>{for(;;){let e=await nextTurnDelivery({cursor:n,hasWorkingTasks:()=>workingTasks(sessionTaskTable(n)).length>0,ignore,inbox:i,queue:o});if(e.kind===`prewarm`){if(u&&a.caller===void 0&&workingTasks(sessionTaskTable(n)).length===0&&o.pendingCount===0&&!i.hasPending()){let t=c?.getDeadline(),n=await r.tryPrewarmTransfer(transferState(),e.targetDeploymentId,t);if(n.kind===`transferred`)return n}continue}if(e.kind===`workflow`){await s.handleWorkflowMessage(e.message);continue}if(e.kind===`cancel-working-tasks`){if(await cancelWorkingTasks(n,`turn-cancelled`),e.origin!==void 0){let t=controlDeliveryOf(e.origin);await n.advance(e=>settleControlDeliveryStep({...e,settlement:{control:t,outcome:`applied`,source:`cancel`}}))}continue}if(!(e.kind===`expired`&&c!==void 0&&((o.pendingCount>0||i.hasPending())&&c.recordActivity(),await c.handleTimerElapsed()===`extended`)))return e}},p=e.initialTurnControl??(e.anchor.kind===`self`?createTurnControl():void 0),m=!1,runTurn=async e=>{let t=a.caller,r=p;p=void 0,a.turnId=e?.control===void 0?turnCoordinates(storedProjection(n.sessionState.snapshot.session.state)).turnId:void 0;let i=await s.runTurn(e,{caller:t,control:r});return a.turnId=void 0,c?.recordActivity(),i.caller!==void 0&&(a.caller=i.caller),i.compacted===!0&&(m=!0),i},transferState=()=>({admittedDeliveryKeys:o.admittedDeliveryKeys,history:n.history,serializedContext:n.serializedContext,sessionState:n.sessionState}),compactionHandoffReady=()=>m&&a.caller===void 0&&workingTasks(sessionTaskTable(n)).length===0,tryCompactionHandoff=async()=>{if(!compactionHandoffReady()||o.pendingCount>0||i.hasPending())return;let e=await r.tryCompactionTransfer(transferState());return e.kind===`transferred`?e:void 0},runDeliveredTurn=async e=>{let t=await r.tryTransfer(e,transferState());return t.kind===`transferred`?t:(e.delivery.caller!==void 0&&(a.caller=e.delivery.caller),{action:await runTurn({delivery:e.delivery}),kind:`action`})},settleCancelledTurn=async(e,t)=>{let r=await n.advanceWithHistory(n=>settleCancelledTurnStep({...n,control:t,reportUsage:e}));return a.caller=void 0,r},awaitPrewarmedAction=async()=>{for(;;){let e=await nextParkedActivity();switch(d=!1,e.kind){case`reset`:return{kind:`terminal`,outcome:expired(e.origin&&controlDeliveryOf(e.origin))};case`closed`:return i.takenOver?await r.adoptTakeover():{kind:`terminal`,outcome:expired()};case`transferred`:return e;case`expired`:return{kind:`terminal`,outcome:expired()};case`clear`:case`compact`:e.origin!==void 0&&await ignore({control:controlDeliveryOf(e.origin),outcome:`ignored`,source:e.kind});continue;case`turn`:return await runDeliveredTurn(e);case`cancel-turn`:continue}}},runInitialAction=async()=>{switch(e.compactFirst===!0&&(await runTurn({control:`compact`}),m=!1),e.start.kind){case`first-message`:return d=!0,u=!1,l=n.advanceBeside(({serializedContext:e,sessionState:t})=>prewarmSessionStep({serializedContext:e,sessionState:t}),()=>d).then(()=>void 0,()=>void 0).finally(()=>{u=!0}),await awaitPrewarmedAction();case`parked`:return{action:{kind:`park`},kind:`action`};case`turn`:{let{input:t}=e.start;return{action:await runTurn(t===void 0?void 0:{delivery:t}),kind:`action`}}}};try{let[t,n]=await Promise.allSettled([runInitialAction(),c?.start()]);if(n.status===`rejected`)throw n.reason;if(t.status===`rejected`)throw t.reason;let o=t.value;if(o.kind!==`action`)return o;let l=o.action;for(;;){if(l.kind===`done`)return{kind:`terminal`,outcome:{action:l,kind:`done`}};if(await settleUnstarted(),l.cancelled===!0){let{caller:t}=a,n=await settleCancelledTurn(t!==void 0,l.cancelledBy);if(t!==void 0){let r={caller:t,sessionId:e.sessionId};await notifyCancelledTaskCallerStep(n.usage===void 0?r:{...r,usage:n.usage})}}else l.settled!==void 0&&(a.caller!==void 0&&await notifyTurnCallerStep({caller:a.caller,lifecycle:`parked`,sessionId:e.sessionId,settled:l.settled}),a.caller=void 0);let t=await tryCompactionHandoff();if(t!==void 0)return t;p??=createTurnControl();let n=await nextParkedActivity();switch(n.kind){case`reset`:return{kind:`terminal`,outcome:resetOutcome(n.origin)};case`closed`:return i.takenOver?await r.adoptTakeover():{kind:`terminal`,outcome:{kind:`expired`}};case`transferred`:return n;case`expired`:return{kind:`terminal`,outcome:{kind:`expired`}};case`clear`:case`compact`:l=await runTurn(n.origin===void 0?{control:n.kind}:{control:n.kind,controlDelivery:controlDeliveryOf(n.origin)});continue;case`cancel-turn`:await s.cancelTurnWork(),await settleCancelledTurn(!1,n.origin===void 0?void 0:controlDeliveryOf(n.origin)),c?.recordActivity(),l={...l,settled:void 0};continue;case`turn`:{let e=await runDeliveredTurn(n);if(e.kind!==`action`)return e;l=e.action;continue}}}}finally{d=!1,await l,await c?.dispose()}}function resetOutcome(e){return e===void 0?{kind:`expired`}:{control:controlDeliveryOf(e),kind:`expired`}}export{failSession,runPreparedSession};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{resolveRuntimeCompiledArtifactsVersionedCacheKey}from"#runtime/cache-key.js";import{defaultDeliverResult,getAdapterKind}from"#channel/adapter.js";import{contextStorage}from"#context/container.js";import{AuthKey,CapabilitiesKey,ChannelDeliveryKey,ChannelInstrumentationKey,HandleEventKey,InitiatorAuthKey,OccurrenceIdKey,ParentSessionKey,SandboxKey,ScheduleIdKey,ScheduleInstanceKey,SessionKey,SessionPredecessorKey,SessionTitleKey,StaticModelReferenceKey,TurnDeliveryIdsKey}from"#context/keys.js";import{bindMemoryInstrumentation}from"#reactions/kinds/memory.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{sandboxProvider}from"#context/providers/sandbox.js";import{isBetweenTurns,storedProjection,turnPosition}from"#harness/session-machine/view.js";import{currentProjection,enterSessionProjection,enterSessionProjectionAt,nextLinePosition,recordAppliedSession,saveSessionProjection}from"#harness/session-machine/current.js";import{ConnectionRegistryKey,connectionProvider}from"#context/providers/connection.js";import{sessionProvider}from"#context/providers/session.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{runStep,withContextScope}from"#context/run-step.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{createDurableSessionValues,readDurableSession}from"#execution/durable-session-store.js";import{readHitlState}from"#harness/hitl/index.js";import*as agentTraceState from"#tracing/eve/agent-trace-context-store.js";import{coalesceTurnInputs,validateHarnessModelMessages}from"#harness/messages.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey}from"#harness/authorization.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{resolveEffectiveAgentRuntime,resolveSessionUsageLimit}from"#execution/effective-agent-config.js";import{checksSessionEvents,foldOrphanedLines,openSessionEventPublisher,readOrphanedLines}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/step-state-delta.js";import{dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{matchSignIns,receive}from"#harness/session-machine/transitions.js";import{readPendingHistory,withoutPendingHistory}from"#execution/session/pending-history.js";import{fact}from"#harness/facts.js";import{admitDeliveries}from"#execution/session/delivery-facts.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{setChannelContext}from"#execution/channel-context.js";import{applyReactionEffects,restoreReactions}from"#reactions/runner.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{eventsOf}from"#harness/publication.js";import{bindSessionInstrumentation}from"#instrumentation/runtime.js";import{deriveSessionTitle}from"#execution/eve-workflow-attributes.js";import{isTurnCancellation,throwIfTurnAborted}from"#harness/turn-cancellation.js";import{bindTurnCallerContext}from"#subagents/parent-notification.js";import{traceSessionHandover}from"#execution/session/handover-tracing.js";import{createCancelledModelCallBatchResult}from"#execution/cancelled-model-call-batch.js";import{pausedOrParked,resolveSessionStepResult}from"#execution/session/turn-step-result.js";import{startSessionPrewarmers}from"#context/prewarm.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{readInterruptedAttempt,recoverInterruptedStep}from"#execution/session/interrupted-step.js";import{stepDisagreement}from"#execution/session/step-decision-check.js";import{createTurnEventHandler}from"#execution/session/turn-event-handler.js";import{buildRuntimeIdentity,createExecutionNodeStep}from"#execution/node-step.js";import{runModelCallBatch}from"#execution/model-call-batching.js";const log=createLogger(`execution.turn-step`);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),o=await deserializeContext(e.serializedContext);enterSessionProjection(o,a.state);let s=await readOrphanedLines({sessionId:a.sessionId,position:nextLinePosition(o),sessionWritable:e.sessionWritable,always:e.recover!==void 0}),c=s.length>0||e.recover!==void 0?readInterruptedAttempt(nextLinePosition(o),s):void 0;s.length>0&&enterSessionProjectionAt(o,foldOrphanedLines(currentProjection(o),s));let l=o.require(ChannelKey),u=o.require(BundleKey),d=resolveEffectiveAgentRuntime(u,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:f}=readHitlState(a.state),p;if(f.length>0&&r!==void 0){let{matches:e,remainingPayloads:t}=matchAuthorizationCallbacks(f,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),p=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 m=o.get(AuthKey),h=o.has(InitiatorAuthKey);r?.auth!==void 0&&(o.set(AuthKey,r.auth??null),o.has(InitiatorAuthKey)||o.set(InitiatorAuthKey,r.auth??null));let g=r===void 0?p?.find(({challenge:e})=>e.candidateId===void 0)?.challenge.requester:void 0;g!==void 0&&o.set(AuthKey,g);let _={...hydrateDurableSession({compactionOverrides:{thresholdPercent:d.thresholdPercent},durable:a,turnAgent:d.turnAgent}),history:validateHarnessModelMessages(e.history)},v=bindSessionInstrumentation({agentName:d.turnAgent.id,ctx:o,rootSessionId:_.rootSessionId??_.sessionId,sessionId:_.sessionId});bindMemoryInstrumentation(o,v?.memory);let 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})),v?.prepareDelivery(n));let 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 s={...u.graph.root,turnAgent:d.turnAgent},f=resolveSessionUsageLimit(u),g=!1,T=createTurnEventHandler({abortSignal:w,canCancelTurn:e.input?.control===void 0,conversation:_.history,hookCancellation:C,publisher:x}),handleEvent=async(e,t)=>{eventsOf(e).some(e=>e.type===`context.settled`&&e.data.kind===`compaction`&&e.data.outcome===`completed`)&&(g=!0),await T(e,t)},E=r!==void 0&&!b?structuredClone(S.state):void 0,D,O;if(r!==void 0){let e=[],t=r.payloads.some(e=>e.message!==void 0)?readPendingHistory(a.state):[],i=0;try{for(let n of r.payloads){let r=l.deliver?await l.deliver(n,S):defaultDeliverResult(n);if(r==null){e.push({input:void 0,payload:n});continue}let a=[...i===0?t:[],...n.history??[]];i+=1,e.push({input:a.length===0?r:{...r,history:a},payload:n})}}catch(e){throw await v?.flush(),e}O=admitDeliveries({channelKind:o.get(ChannelInstrumentationKey)?.kind??getAdapterKind(l),delivery:n??r,status:e=>currentProjection(o).view.deliveries[e]?.status,payloads:e}),i>0&&t.length>0&&(_={..._,state:withoutPendingHistory(_.state)}),D=O.inputs.length===0?void 0:O.inputs.reduce(coalesceTurnInputs)}let k=r?.auth===void 0?void 0:attributeAnswers({responder:r.auth,state:a.state,stepInput:D});if(k!==void 0&&(D=k,m===void 0?o.delete(AuthKey):o.set(AuthKey,m),h||o.delete(InitiatorAuthKey)),r!==void 0&&D===void 0&&!b)m===void 0?o.delete(AuthKey):o.set(AuthKey,m),S.state=E;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),D={...D,delegatedUsage:i.delegatedUsage,runtimeActionResults:i.results}),n!==void 0){let e={...l,state:{...S.state}};setChannelContext(o,e)}let A=!1,admissionFacts=e=>{if(O===void 0||O.facts.length===0)return[];let t=[];if(!turnPosition(currentProjection(o)).sessionStarted){let n=o.get(ParentSessionKey),r=o.get(SessionPredecessorKey);t.push(fact(`session.started`,{parent:n===void 0?void 0:{callId:n.callId,sessionId:n.sessionId},predecessor:r,runtime:e}))}return[...t,...O.facts]},publishAdmission=async e=>{let t=admissionFacts(e);if(t.length===0)return;let n=sessionProvider.create(o,_);o.setVirtualContext(SessionKey,n.value);let r=await connectionProvider.create(o,_);r!==void 0&&o.setVirtualContext(ConnectionRegistryKey,r.value);let i=await sandboxProvider.create(o,_);i!==void 0&&o.setVirtualContext(SandboxKey,i.value);let a=v?.createHandleEvent({handleEvent})??handleEvent;try{await contextStorage.run(o,()=>a(t))}finally{if(i!==void 0){let e=await i.value.captureState();JSON.stringify(e)!==JSON.stringify(_.sandboxState??null)&&(A=!0,_={..._,sandboxState:e})}}},consumeCancelledInput=async()=>{let e=currentProjection(o),t=(D?.deliveries??[]).filter(({deliveryId:t})=>e.view.deliveries[t]?.status===`admitted`);if(t.length===0)return;let{events:n}=receive(sessionView(e,_.state),{deliveries:t}),r=createTurnEventHandler({abortSignal:w,canCancelTurn:!1,conversation:_.history,hookCancellation:new AbortController,publisher:x}),i=v?.createHandleEvent({handleEvent:r})??r;await contextStorage.run(o,()=>i(n))};if(r!==void 0&&D===void 0&&b){await publishAdmission(buildRuntimeIdentity(s)).catch(ignoreTurnCancellation),await v?.flush();let t=saveSessionProjection(reconcileSessionContinuationToken(o,_),o),n=serializeContext(o),r=t===_&&!A?{history:e.history,sessionState:e.sessionState}:createDurableSessionValues(t);return pausedOrParked(t,{serializedContext:n,...r})}let j=buildRuntimeIdentity(s),M,prepareReactions=e=>(o.setVirtualContext(StaticModelReferenceKey,d.turnAgent.model??null),M??=(async()=>{try{let t=process.env.VERCEL_DEPLOYMENT_ID?.trim(),n=t?`deployment:${t}`:await resolveRuntimeCompiledArtifactsVersionedCacheKey(u.compiledArtifactsSource);await contextStorage.run(o,()=>restoreReactions(o,{abortSignal:w,conversation:e.history,revision:n}))}catch(e){throw await v?.flush(),e}})());if(c!==void 0){let t=await recoverInterruptedStep({admission:admissionFacts(j),attempt:c,control:e.input?.control===void 0?void 0:{delivery:e.input.controlDelivery,kind:e.input.control},ctx:o,failed:e.recover,publish:async(e,t)=>(await withContextScope(o,t,async t=>{await prepareReactions(t);let n=createTurnEventHandler({abortSignal:w,canCancelTurn:!1,conversation:t.history,hookCancellation:new AbortController,publisher:x});return await(v?.createHandleEvent({handleEvent:n})??n)(e),{result:void 0,session:t}})).session,session:_,stepInput:D}).catch(async e=>{throw await v?.flush(),e});if(`result`in t)return await v?.flush(),t.result.action===`done`&&await x.writer.close().catch(()=>{}),t.result;_=t.session,D=t.stepInput}await prepareReactions(_);try{await publishAdmission(j)}catch(e){if(!isTurnCancellation(e))throw await v?.flush(),e}let N=u.resolvedAgent.config?.experimental?.workflow?.modelCallsPerStep??1,P=o.get(CapabilitiesKey),runHarnessStep=async(n,r,i)=>{let a=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:d.thresholdPercent},session:n,turnAgent:d.turnAgent});return createExecutionNodeStep({steeringSignal:e.steeringSignal,abortSignal:w,capabilities:P,clearOnly:e.input?.control===`clear`,compactOnly:e.input?.control===`compact`,controlDelivery:e.input?.controlDelivery,createRuntime:createWorkflowRuntime,handleEvent,signInCompletions:i,typedAnswers:!hasDelegatedSessionContext(e.serializedContext),instrumentation:v,modelResolutionScope:{moduleMap:u.moduleMap,nodeId:u.nodeId},node:s,sessionUsageLimit:f,titleAttributeWrite:t.title})(a,r)},F,I;try{throwIfTurnAborted(w),I=await runModelCallBatch({steeringSignal:e.steeringSignal,initialInput:D,initialSession:_,modelCallsPerStep:N,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,d.turnAgent.model??null);let i=t&&D?.outputSchema!==void 0?{...n,outputSchema:D.outputSchema}:n;await applyReactionEffects(o);let a=t&&p!==void 0?p.map(({challenge:e})=>e):void 0,s=await runHarnessStep(i,r,a);return await x.finish({announce:stoppedForPerson(s)}),s});i.settledTurn===void 0&&throwIfTurnAborted(w);let a={...i,session:saveSessionProjection(i.session,o)};return recordAppliedSession(o,a.session),F={result:a,serializedContext:serializeContext(o)},a}})}catch(t){if(!isTurnCancellation(t)&&!w.aborted)throw await v?.flush(),t;return F===void 0&&await consumeCancelledInput(),createCancelledModelCallBatchResult({beforeBatchContext:e.serializedContext,checkpoint:F,ctx:o,initialSession:_,stepInput:D})}let L=saveSessionProjection(dropClosedRecords(reconcileSessionContinuationToken(o,I.session),currentProjection(o)),o);agentTraceState.pruneAgentTraceState(o,L.sessionId,L.state);let R=serializeContext(o);I={...I,session:L};let z=resolveSessionStepResult(I,R);if(checksSessionEvents()){let e=stepDisagreement(z,currentProjection(o).view);e!==void 0&&e!==`dispatch-deferred`&&log.warn(`a turn step's decision disagrees with the session's tables`,{disagreement:e})}return z.action===`done`&&await x.writer.close(),g?{...z,compacted:!0}:z}finally{x.writer.release()}}function stoppedForPerson(e){return e.held===void 0?e.next===null&&e.settledTurn===void 0:e.held.kind===`request`}function ignoreTurnCancellation(e){if(!isTurnCancellation(e))throw e}export{turnStep};
1
+ import{createLogger}from"#internal/logging.js";import{resolveRuntimeCompiledArtifactsVersionedCacheKey}from"#runtime/cache-key.js";import{defaultDeliverResult,getAdapterKind}from"#channel/adapter.js";import{contextStorage}from"#context/container.js";import{AuthKey,CapabilitiesKey,ChannelDeliveryKey,ChannelInstrumentationKey,HandleEventKey,InitiatorAuthKey,OccurrenceIdKey,ParentSessionKey,SandboxKey,ScheduleIdKey,ScheduleInstanceKey,SessionKey,SessionPredecessorKey,SessionTitleKey,StaticModelReferenceKey,ToolChannelKey,TurnDeliveryIdsKey}from"#context/keys.js";import{bindMemoryInstrumentation}from"#reactions/kinds/memory.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{sandboxProvider}from"#context/providers/sandbox.js";import{isBetweenTurns,storedProjection,turnPosition}from"#harness/session-machine/view.js";import{currentProjection,enterSessionProjection,enterSessionProjectionAt,nextLinePosition,recordAppliedSession,saveSessionProjection}from"#harness/session-machine/current.js";import{ConnectionRegistryKey,connectionProvider}from"#context/providers/connection.js";import{sessionProvider}from"#context/providers/session.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";import{hasDelegatedSessionContext}from"#execution/delegated-session-context.js";import{resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{runStep,withContextScope}from"#context/run-step.js";import{deserializeContext,serializeContext}from"#context/serialize.js";import{createDurableSessionValues,readDurableSession}from"#execution/durable-session-store.js";import{readHitlState}from"#harness/hitl/index.js";import*as agentTraceState from"#tracing/eve/agent-trace-context-store.js";import{coalesceTurnInputs,validateHarnessModelMessages}from"#harness/messages.js";import{CallbackBaseUrlKey,PendingAuthorizationResultKey}from"#harness/authorization.js";import{hydrateDurableSession,refreshSessionFromTurnAgent}from"#execution/session.js";import{resolveEffectiveAgentRuntime,resolveSessionUsageLimit}from"#execution/effective-agent-config.js";import{checksSessionEvents,foldOrphanedLines,openSessionEventPublisher,readOrphanedLines}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/step-state-delta.js";import{dropClosedRecords,saveTransition,sessionView}from"#harness/session-machine/commit.js";import{matchSignIns,receive}from"#harness/session-machine/transitions.js";import{readPendingHistory,withoutPendingHistory}from"#execution/session/pending-history.js";import{fact}from"#harness/facts.js";import{admitDeliveries}from"#execution/session/delivery-facts.js";import{setChannelContext}from"#execution/channel-context.js";import{applyReactionEffects,restoreReactions}from"#reactions/runner.js";import{reconcileSessionContinuationToken}from"#execution/reconcile-session-continuation-token.js";import{eventsOf}from"#harness/publication.js";import{bindSessionInstrumentation}from"#instrumentation/runtime.js";import{deriveSessionTitle}from"#execution/eve-workflow-attributes.js";import{isTurnCancellation,throwIfTurnAborted}from"#harness/turn-cancellation.js";import{bindTurnCallerContext}from"#subagents/parent-notification.js";import{traceSessionHandover}from"#execution/session/handover-tracing.js";import{createCancelledModelCallBatchResult}from"#execution/cancelled-model-call-batch.js";import{pausedOrParked,resolveSessionStepResult}from"#execution/session/turn-step-result.js";import{startSessionPrewarmers}from"#context/prewarm.js";import{createToolChannelTo}from"#execution/tools/channel-to.js";import{channelOf}from"#reactions/frame.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{readInterruptedAttempt,recoverInterruptedStep}from"#execution/session/interrupted-step.js";import{stepDisagreement}from"#execution/session/step-decision-check.js";import{createTurnEventHandler}from"#execution/session/turn-event-handler.js";import{buildRuntimeIdentity,createExecutionNodeStep}from"#execution/node-step.js";import{runModelCallBatch}from"#execution/model-call-batching.js";const log=createLogger(`execution.turn-step`);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),o=await deserializeContext(e.serializedContext);enterSessionProjection(o,a.state);let s=await readOrphanedLines({sessionId:a.sessionId,position:nextLinePosition(o),sessionWritable:e.sessionWritable,always:e.recover!==void 0}),c=s.length>0||e.recover!==void 0?readInterruptedAttempt(nextLinePosition(o),s):void 0;s.length>0&&enterSessionProjectionAt(o,foldOrphanedLines(currentProjection(o),s));let l=o.require(ChannelKey),u=o.require(BundleKey),d=resolveEffectiveAgentRuntime(u,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:f}=readHitlState(a.state),p;if(f.length>0&&r!==void 0){let{matches:e,remainingPayloads:t}=matchAuthorizationCallbacks(f,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),p=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 m=o.get(AuthKey),h=o.has(InitiatorAuthKey);r?.auth!==void 0&&(o.set(AuthKey,r.auth??null),o.has(InitiatorAuthKey)||o.set(InitiatorAuthKey,r.auth??null));let g=r===void 0?p?.find(({challenge:e})=>e.candidateId===void 0)?.challenge.requester:void 0;g!==void 0&&o.set(AuthKey,g);let _={...hydrateDurableSession({compactionOverrides:{thresholdPercent:d.thresholdPercent},durable:a,turnAgent:d.turnAgent}),history:validateHarnessModelMessages(e.history)},v=bindSessionInstrumentation({agentName:d.turnAgent.id,ctx:o,rootSessionId:_.rootSessionId??_.sessionId,sessionId:_.sessionId});bindMemoryInstrumentation(o,v?.memory);let 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})),v?.prepareDelivery(n));let 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 s={...u.graph.root,turnAgent:d.turnAgent},f=resolveSessionUsageLimit(u),g=!1,T=createTurnEventHandler({abortSignal:w,canCancelTurn:e.input?.control===void 0,conversation:_.history,hookCancellation:C,publisher:x}),handleEvent=async(e,t)=>{eventsOf(e).some(e=>e.type===`context.settled`&&e.data.kind===`compaction`&&e.data.outcome===`completed`)&&(g=!0),await T(e,t)},E=r!==void 0&&!b?structuredClone(S.state):void 0,D,O;if(r!==void 0){let e=[],t=r.payloads.some(e=>e.message!==void 0)?readPendingHistory(a.state):[],i=0;try{for(let n of r.payloads){let r=l.deliver?await l.deliver(n,S):defaultDeliverResult(n);if(r==null){e.push({input:void 0,payload:n});continue}let a=[...i===0?t:[],...n.history??[]];i+=1,e.push({input:a.length===0?r:{...r,history:a},payload:n})}}catch(e){throw await v?.flush(),e}O=admitDeliveries({channelKind:o.get(ChannelInstrumentationKey)?.kind??getAdapterKind(l),delivery:n??r,status:e=>currentProjection(o).view.deliveries[e]?.status,payloads:e}),i>0&&t.length>0&&(_={..._,state:withoutPendingHistory(_.state)}),D=O.inputs.length===0?void 0:O.inputs.reduce(coalesceTurnInputs)}let k=r?.auth===void 0?void 0:attributeAnswers({responder:r.auth,state:a.state,stepInput:D});if(k!==void 0&&(D=k,m===void 0?o.delete(AuthKey):o.set(AuthKey,m),h||o.delete(InitiatorAuthKey)),r!==void 0&&D===void 0&&!b)m===void 0?o.delete(AuthKey):o.set(AuthKey,m),S.state=E;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),D={...D,delegatedUsage:i.delegatedUsage,runtimeActionResults:i.results}),n!==void 0){let e={...l,state:{...S.state}};setChannelContext(o,e)}let A=!1,admissionFacts=e=>{if(O===void 0||O.facts.length===0)return[];let t=[];if(!turnPosition(currentProjection(o)).sessionStarted){let n=o.get(ParentSessionKey),r=o.get(SessionPredecessorKey);t.push(fact(`session.started`,{parent:n===void 0?void 0:{callId:n.callId,sessionId:n.sessionId},predecessor:r,runtime:e}))}return[...t,...O.facts]},publishAdmission=async e=>{let t=admissionFacts(e);if(t.length===0)return;let n=sessionProvider.create(o,_);o.setVirtualContext(SessionKey,n.value);let r=await connectionProvider.create(o,_);r!==void 0&&o.setVirtualContext(ConnectionRegistryKey,r.value);let i=await sandboxProvider.create(o,_);i!==void 0&&o.setVirtualContext(SandboxKey,i.value);let a=v?.createHandleEvent({handleEvent})??handleEvent;try{await contextStorage.run(o,()=>a(t))}finally{if(i!==void 0){let e=await i.value.captureState();JSON.stringify(e)!==JSON.stringify(_.sandboxState??null)&&(A=!0,_={..._,sandboxState:e})}}},consumeCancelledInput=async()=>{let e=currentProjection(o),t=(D?.deliveries??[]).filter(({deliveryId:t})=>e.view.deliveries[t]?.status===`admitted`);if(t.length===0)return;let{events:n}=receive(sessionView(e,_.state),{deliveries:t}),r=createTurnEventHandler({abortSignal:w,canCancelTurn:!1,conversation:_.history,hookCancellation:new AbortController,publisher:x}),i=v?.createHandleEvent({handleEvent:r})??r;await contextStorage.run(o,()=>i(n))};if(r!==void 0&&D===void 0&&b){await publishAdmission(buildRuntimeIdentity(s)).catch(ignoreTurnCancellation),await v?.flush();let t=saveSessionProjection(reconcileSessionContinuationToken(o,_),o),n=serializeContext(o),r=t===_&&!A?{history:e.history,sessionState:e.sessionState}:createDurableSessionValues(t);return pausedOrParked(t,{serializedContext:n,...r})}let j=buildRuntimeIdentity(s),M,prepareReactions=e=>(o.setVirtualContext(StaticModelReferenceKey,d.turnAgent.model??null),M??=(async()=>{try{let t=process.env.VERCEL_DEPLOYMENT_ID?.trim(),n=t?`deployment:${t}`:await resolveRuntimeCompiledArtifactsVersionedCacheKey(u.compiledArtifactsSource);await contextStorage.run(o,()=>restoreReactions(o,{abortSignal:w,conversation:e.history,revision:n}))}catch(e){throw await v?.flush(),e}})());if(c!==void 0){let t=await recoverInterruptedStep({admission:admissionFacts(j),attempt:c,control:e.input?.control===void 0?void 0:{delivery:e.input.controlDelivery,kind:e.input.control},ctx:o,failed:e.recover,publish:async(e,t)=>(await withContextScope(o,t,async t=>{await prepareReactions(t);let n=createTurnEventHandler({abortSignal:w,canCancelTurn:!1,conversation:t.history,hookCancellation:new AbortController,publisher:x});return await(v?.createHandleEvent({handleEvent:n})??n)(e),{result:void 0,session:t}})).session,session:_,stepInput:D}).catch(async e=>{throw await v?.flush(),e});if(`result`in t)return await v?.flush(),t.result.action===`done`&&await x.writer.close().catch(()=>{}),t.result;_=t.session,D=t.stepInput}await prepareReactions(_);try{await publishAdmission(j)}catch(e){if(!isTurnCancellation(e))throw await v?.flush(),e}let N=u.resolvedAgent.config?.experimental?.workflow?.modelCallsPerStep??1,P=o.get(CapabilitiesKey),runHarnessStep=async(n,r,i)=>{let a=refreshSessionFromTurnAgent({compactionOverrides:{thresholdPercent:d.thresholdPercent},session:n,turnAgent:d.turnAgent});return createExecutionNodeStep({steeringSignal:e.steeringSignal,abortSignal:w,capabilities:P,clearOnly:e.input?.control===`clear`,compactOnly:e.input?.control===`compact`,controlDelivery:e.input?.controlDelivery,createRuntime:createWorkflowRuntime,handleEvent,signInCompletions:i,typedAnswers:!hasDelegatedSessionContext(e.serializedContext),instrumentation:v,modelResolutionScope:{moduleMap:u.moduleMap,nodeId:u.nodeId},node:s,sessionUsageLimit:f,titleAttributeWrite:t.title})(a,r)},F,I;try{throwIfTurnAborted(w),I=await runModelCallBatch({steeringSignal:e.steeringSignal,initialInput:D,initialSession:_,modelCallsPerStep:N,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,d.turnAgent.model??null),o.setVirtualContext(ToolChannelKey,{channel:channelOf(o),to:createToolChannelTo({delegated:hasDelegatedSessionContext(e.serializedContext),loadBundle:()=>o.require(BundleKey)})});let i=t&&D?.outputSchema!==void 0?{...n,outputSchema:D.outputSchema}:n;await applyReactionEffects(o);let a=t&&p!==void 0?p.map(({challenge:e})=>e):void 0,s=await runHarnessStep(i,r,a);return await x.finish({announce:stoppedForPerson(s)}),s});i.settledTurn===void 0&&throwIfTurnAborted(w);let a={...i,session:saveSessionProjection(i.session,o)};return recordAppliedSession(o,a.session),F={result:a,serializedContext:serializeContext(o)},a}})}catch(t){if(!isTurnCancellation(t)&&!w.aborted)throw await v?.flush(),t;return F===void 0&&await consumeCancelledInput(),createCancelledModelCallBatchResult({beforeBatchContext:e.serializedContext,checkpoint:F,ctx:o,initialSession:_,stepInput:D})}let L=saveSessionProjection(dropClosedRecords(reconcileSessionContinuationToken(o,I.session),currentProjection(o)),o);agentTraceState.pruneAgentTraceState(o,L.sessionId,L.state);let R=serializeContext(o);I={...I,session:L};let z=resolveSessionStepResult(I,R);if(checksSessionEvents()){let e=stepDisagreement(z,currentProjection(o).view);e!==void 0&&e!==`dispatch-deferred`&&log.warn(`a turn step's decision disagrees with the session's tables`,{disagreement:e})}return z.action===`done`&&await x.writer.close(),g?{...z,compacted:!0}:z}finally{x.writer.release()}}function stoppedForPerson(e){return e.held===void 0?e.next===null&&e.settledTurn===void 0:e.held.kind===`request`}function ignoreTurnCancellation(e){if(!isTurnCancellation(e))throw e}export{turnStep};
@@ -1 +1 @@
1
- import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{isLocalDevelopmentServer}from"#internal/application/dev-environment.js";import{FatalError}from"#compiled/@workflow/core/index.js";import{UnsafeDestinationError,assertPublicHostname,createPublicDispatcher,fetchWithDispatcher,findUnsafeDestinationError,readBoundedResponse}from"#execution/public-destination.js";const log=createLogger(`execution.session-callback`),VERCEL_CALLBACK_HOST_ENVS=[`VERCEL_URL`,`VERCEL_BRANCH_URL`,`VERCEL_PROJECT_PRODUCTION_URL`],VERCEL_REQUEST_CONTEXT=Symbol.for(`@vercel/request-context`);async function postSessionCallbackRequest(e){let t=e.timeoutMs??3e4,n=AbortSignal.timeout(t),r;try{r=await requestCallback(e.url,{body:JSON.stringify(e.body),headers:await resolveSessionCallbackHeaders(e.url),signal:n})}catch(r){let i=findUnsafeDestinationError(r);throw i===void 0?(e.logFailures!==!1&&log.error(`callback delivery failed`,{...callbackLogFields(e),failure:n.aborted?`timeout`:`transport`,timeoutMs:t,error:Error(`Callback request failed before receiving a response.`)}),r):(e.logFailures!==!1&&log.error(`callback delivery failed`,{...callbackLogFields(e),failure:`blocked-destination`,error:Error(i.message)}),new FatalError(`Callback delivery refused: ${i.message}`))}return!r.ok&&e.logFailures!==!1&&log.error(`callback delivery failed`,{...callbackLogFields(e),failure:`http`,statusCode:r.status,error:Error(`Callback request failed with HTTP ${r.status}.`)}),r}async function requestCallback(e,t){let n=new URL(e);if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new UnsafeDestinationError(`Callback URL must use http or https.`);let r={allowLoopback:isLocalDevelopmentServer()};assertPublicHostname(n.hostname,r);let i=await createPublicDispatcher(r);try{let n=await fetchWithDispatcher(e,{...t,dispatcher:i,method:`POST`,redirect:`error`});return await readBoundedResponse(n,65536)}finally{await i.close()}}function callbackLogFields(e){let t=URL.parse(e.url),n=t?.pathname.match(/^(.*?\/(?:callback|activity))\//)?.[1],r={callbackOrigin:t?.origin,callbackPath:n===void 0?`[redacted]`:`${n}/[redacted]`};if(isObject(e.body)){for(let t of[`kind`,`callId`,`sessionId`,`childSessionId`,`subagentName`,`updateEpoch`])typeof e.body[t]==`string`&&(r[t]=e.body[t]);typeof e.body.updateIndex==`number`&&(r.updateIndex=e.body.updateIndex)}return r}async function resolveSessionCallbackHeaders(e){let t={"content-type":`application/json`};if(process.env.VERCEL!==`1`)return t;let n;try{n=new URL(e)}catch{return t}let r=VERCEL_CALLBACK_HOST_ENVS.some(e=>process.env[e]?.trim().toLowerCase()===n.hostname.toLowerCase());if(n.protocol!==`https:`||!r)return t;let i=readAmbientVercelOidcToken();return i!==void 0&&(t[`x-vercel-trusted-oidc-idp-token`]=i),t}function readAmbientVercelOidcToken(){let e=(globalThis[VERCEL_REQUEST_CONTEXT]?.get?.().headers?.[`x-vercel-oidc-token`]??process.env.VERCEL_OIDC_TOKEN)?.trim();return e===``?void 0:e}export{postSessionCallbackRequest};
1
+ import{createLogger}from"#internal/logging.js";import{isObject}from"#shared/guards.js";import{isLocalDevelopmentServer}from"#internal/application/dev-environment.js";import{FatalError}from"#compiled/@workflow/core/index.js";import{UnsafeDestinationError,assertPublicHostname,createPublicDispatcher,fetchWithDispatcher,findUnsafeDestinationError,readBoundedResponse}from"#execution/public-destination.js";const log=createLogger(`execution.session-callback`),VERCEL_CALLBACK_HOST_ENVS=[`VERCEL_URL`,`VERCEL_BRANCH_URL`,`VERCEL_PROJECT_PRODUCTION_URL`],VERCEL_REQUEST_CONTEXT=Symbol.for(`@vercel/request-context`);async function postSessionCallbackRequest(e){let t=e.timeoutMs??3e4,n=AbortSignal.timeout(t),r=await resolveSessionCallbackHeaders(e.url),i;try{i=await requestCallback(e.url,{body:JSON.stringify(e.body),headers:r,signal:n})}catch(r){let i=findUnsafeDestinationError(r);throw i===void 0?(e.logFailures!==!1&&log.error(`callback delivery failed`,{...callbackLogFields(e),failure:n.aborted?`timeout`:`transport`,timeoutMs:t,error:Error(`Callback request failed before receiving a response.`)}),r):(e.logFailures!==!1&&log.error(`callback delivery failed`,{...callbackLogFields(e),failure:`blocked-destination`,error:Error(i.message)}),new FatalError(`Callback delivery refused: ${i.message}`))}return!i.ok&&e.logFailures!==!1&&log.error(`callback delivery failed`,{...callbackLogFields(e),failure:`http`,statusCode:i.status,error:Error(`Callback request failed with HTTP ${i.status}.`)}),i}async function requestCallback(e,t){let n=new URL(e);if(n.protocol!==`http:`&&n.protocol!==`https:`)throw new UnsafeDestinationError(`Callback URL must use http or https.`);let r={allowLoopback:isLocalDevelopmentServer()};assertPublicHostname(n.hostname,r);let i=await createPublicDispatcher(r);try{let n=await fetchWithDispatcher(e,{...t,dispatcher:i,method:`POST`,redirect:`error`});return await readBoundedResponse(n,65536)}finally{await i.close()}}function callbackLogFields(e){let t=URL.parse(e.url),n=t?.pathname.match(/^(.*?\/(?:callback|activity))\//)?.[1],r={callbackOrigin:t?.origin,callbackPath:n===void 0?`[redacted]`:`${n}/[redacted]`};if(isObject(e.body)){for(let t of[`kind`,`callId`,`sessionId`,`childSessionId`,`subagentName`,`updateEpoch`])typeof e.body[t]==`string`&&(r[t]=e.body[t]);typeof e.body.updateIndex==`number`&&(r.updateIndex=e.body.updateIndex)}return r}async function resolveSessionCallbackHeaders(e){let t={"content-type":`application/json`};if(process.env.VERCEL!==`1`)return t;let n;try{n=new URL(e)}catch{return t}let r=VERCEL_CALLBACK_HOST_ENVS.some(e=>{let t=process.env[e]?.trim();return t!==void 0&&t!==``&&URL.parse(`https://${t}`)?.origin===n.origin});if(n.protocol!==`https:`||!r&&!configuredCallbackOrigins().includes(n.origin))return t;let i=readAmbientVercelOidcToken();return i!==void 0&&(t[`x-vercel-trusted-oidc-idp-token`]=i),t}function configuredCallbackOrigins(){let e=process.env.EVE_CALLBACK_TRUSTED_ORIGINS?.trim();return e?e.split(`,`).map(e=>{let t=URL.parse(e.trim());if(t===null||t.protocol!==`https:`||t.username!==``||t.password!==``||t.pathname!==`/`||t.search!==``||t.hash!==``)throw new FatalError(`EVE_CALLBACK_TRUSTED_ORIGINS must be a comma-separated list of HTTPS origins without credentials, paths, queries, or fragments.`);return t.origin}):[]}function readAmbientVercelOidcToken(){let e=(globalThis[VERCEL_REQUEST_CONTEXT]?.get?.().headers?.[`x-vercel-oidc-token`]??process.env.VERCEL_OIDC_TOKEN)?.trim();return e===``?void 0:e}export{postSessionCallbackRequest};
@@ -1 +1 @@
1
- import{handleAuthorizationError}from"#runtime/connections/scoped-authorization.js";import{buildBaseToolContext}from"#context/build-base-tool-context.js";import{createAuthorizationContext}from"#runtime/authorization-context.js";function createToolExecuteWithAuth(e){return(t,n)=>{let r=createAuthorizationContext({scope:e.scope}),i={...buildBaseToolContext({options:n,toolName:e.scope}),messages:n.messages,getToken:r.getToken,requireAuth:r.requireAuth,...n.approval!==void 0&&{approval:approvalOf(n.approval.responder,r)}};return r.run(()=>e.execute(t,i))}}function approvalOf(e,t){return{responder:{...e,getToken:(n,r)=>t.getResponderToken(e,n,r)}}}function buildApprovalResponseAuth(e){let t=createAuthorizationContext({scope:e.scope,boundResponder:e.responder});return{getToken:(n,r)=>t.getToken(n,namespaceApprovalAuthOptions(e.scope,r)),requireAuth:(n,r)=>t.requireAuth(n,namespaceApprovalAuthOptions(e.scope,r))}}function namespaceApprovalAuthOptions(e,t){return t?.authKey===void 0?t:{...t,authKey:`${e}:${t.authKey}`}}async function handleApprovalResponsePolicyError(e){return await handleAuthorizationError(e)}export{buildApprovalResponseAuth,createToolExecuteWithAuth,handleApprovalResponsePolicyError};
1
+ import{contextStorage}from"#context/container.js";import{ToolChannelKey}from"#context/keys.js";import{handleAuthorizationError}from"#runtime/connections/scoped-authorization.js";import{buildBaseToolContext}from"#context/build-base-tool-context.js";import{createAuthorizationContext}from"#runtime/authorization-context.js";function createToolExecuteWithAuth(e){return(t,n)=>{let r=createAuthorizationContext({scope:e.scope}),i={...buildBaseToolContext({options:n,toolName:e.scope}),messages:n.messages,...contextStorage.getStore()?.get(ToolChannelKey)??{channel:{kind:`unknown`,metadata:{}},to:unavailableChannelTo},getToken:r.getToken,requireAuth:r.requireAuth,...n.approval!==void 0&&{approval:approvalOf(n.approval.responder,r)}};return r.run(()=>e.execute(t,i))}}const unavailableChannelTo=()=>{throw Error(`ctx.to() is only available while a session's turn runs the tool.`)};function approvalOf(e,t){return{responder:{...e,getToken:(n,r)=>t.getResponderToken(e,n,r)}}}function buildApprovalResponseAuth(e){let t=createAuthorizationContext({scope:e.scope,boundResponder:e.responder});return{getToken:(n,r)=>t.getToken(n,namespaceApprovalAuthOptions(e.scope,r)),requireAuth:(n,r)=>t.requireAuth(n,namespaceApprovalAuthOptions(e.scope,r))}}function namespaceApprovalAuthOptions(e,t){return t?.authKey===void 0?t:{...t,authKey:`${e}:${t.authKey}`}}async function handleApprovalResponsePolicyError(e){return await handleAuthorizationError(e)}export{buildApprovalResponseAuth,createToolExecuteWithAuth,handleApprovalResponsePolicyError};
@@ -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),{reply: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({signal: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.84.1//runAgentRouterTask`;export{runAgentRouterTask};
1
+ import{decide}from"#ai/decide.js";async function runAgentRouterTask(e,t){"use workflow";let n=await chooseTarget(e.message,descriptions(t),t.abortSignal),{reply: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({signal: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.85.0//runAgentRouterTask`;export{runAgentRouterTask};
@@ -0,0 +1,12 @@
1
+ import { type CrossChannelToFn } from "#channel/cross-channel-receive.js";
2
+ import type { CompiledRuntimeAgentBundle } from "#runtime/sessions/compiled-agent-cache.js";
3
+ /**
4
+ * `ctx.to()` for a tool or a workflow tool's step: the root agent's channels,
5
+ * reached through their `receive()` hooks as a route's `ctx.to()` reaches them.
6
+ */
7
+ export declare function createToolChannelTo(input: {
8
+ /** Whether a parent, local or remote, delegated the session running the tool. */
9
+ readonly delegated: boolean;
10
+ /** The compiled agent that owns the tool. */
11
+ readonly loadBundle: () => CompiledRuntimeAgentBundle | Promise<CompiledRuntimeAgentBundle>;
12
+ }): CrossChannelToFn;
@@ -0,0 +1 @@
1
+ import{createCrossChannelToFn,toCrossChannelTargets}from"#channel/cross-channel-receive.js";import{ContextContainer,contextStorage}from"#context/container.js";import{createWorkflowRuntime}from"#execution/workflow-runtime.js";function createToolChannelTo(e){return(t,n)=>{if(e.delegated)throw Error(`ctx.to() isn't available in a delegated session (a subagent, a root copy, or a remote agent call): a session it started would outlive the delegation and act for the caller. Return the result to the caller, and send from a tool on the root agent.`);return{async send(r,i){let a=await e.loadBundle(),o=createCrossChannelToFn(createWorkflowRuntime({compiledArtifactsSource:a.compiledArtifactsSource}),toCrossChannelTargets(a.graph.root.channels));return await contextStorage.run(new ContextContainer,()=>o(t,n).send(r,i))}}}}export{createToolChannelTo};
@@ -1,6 +1,7 @@
1
1
  import type { SessionContext } from "#context/session-context.js";
2
2
  import type { AgentSessionContext } from "#execution/agent-sessions/context.js";
3
3
  import { type RunUsageTally } from "#execution/agent-sessions/usage.js";
4
+ import type { InstrumentationChannel } from "#shared/instrumentation-channel.js";
4
5
  import type { WorkflowSharedContext } from "#tools/workflow-definition.js";
5
6
  import { WorkflowToolRunAsks } from "#execution/tools/workflow/ask.js";
6
7
  import type { WorkflowBodyCommand, WorkflowToolRunOutcome, WorkflowToolRunRef } from "#execution/tools/workflow/messages.js";
@@ -75,6 +76,8 @@ export declare function resolveWorkflowEntryPoint<TEntryPoint>(input: WorkflowBo
75
76
  * knows its calls.
76
77
  */
77
78
  export declare function createSharedContext(input: WorkflowBodyInput, agent: WorkflowSharedContext["agent"], askPerson: WorkflowSharedContext["ask"]): Omit<ToolContext & WorkflowSharedContext, "abortSignal" | "agents" | "callId" | "messages" | "session">;
79
+ /** `ctx.channel` for a call: the channel that serves the calling session. */
80
+ export declare function workflowToolChannel(context: AgentSessionContext): InstrumentationChannel;
78
81
  /** `ctx.agents` for a call: the agents its context lists, frozen. */
79
82
  export declare function createAgentsView(context: AgentSessionContext): WorkflowSharedContext["agents"];
80
83
  export declare class WorkflowToolRunCancelledError extends Error {
@@ -1 +1 @@
1
- import{parseJsonValue}from"#shared/json.js";import{callToolStubStep}from"#execution/tool-stubs/steps.js";import{getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{toolStubOutput}from"#tool-stubs/output.js";import{createAgentSessions}from"#execution/agent-sessions/session.js";import{createRunUsageTally}from"#execution/agent-sessions/usage.js";import{WorkflowToolRunAsks,ask,attachWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{readRegisteredWorkflow}from"#execution/workflow-registry.js";import{withToolOutputSerializationError}from"#harness/tool-output-serialization.js";const INTERRUPTED_OUTPUT={interrupted:!0};var WorkflowCallSignals=class{body=new AbortController;run=new AbortController;asks;constructor(e){this.asks=e}get abortSignal(){return this.body.signal}get runSignal(){return this.run.signal}get interrupted(){return this.body.signal.aborted&&!this.run.signal.aborted}get unwinding(){return this.run.signal.aborted}apply(e){switch(e.kind){case`cancel`:case`end`:this.asks.cancelAll(),this.run.abort(new WorkflowToolRunCancelledError(e.reason)),this.body.abort(this.run.signal.reason);return;case`interrupt`:this.body.abort(new WorkflowToolRunInterruptedError);return;case`call`:return}}};function startCallBody(e){let t=createWorkflowBodyRef(e),n=new WorkflowToolRunAsks(t.runId),r=new WorkflowCallSignals(n),i={agentContext:e.agentContext,asks:n,auth:e.session.auth,control:e.hookToken,from:t,owner:e.owner},a=createRunUsageTally(),o=createAgentSessions(i,a),s=createCallContext(e,r,o.open);return attachWorkflowToolRunContext(s,i),{asks:n,close:o.close,control:r,outcome:executeCallBody(e,s,r,t),usage:a}}async function executeCallBody(e,t,n,r){try{let n=findStubTarget(e.agentContext.toolStubs,e.toolName);if(n!==void 0){let t=await callToolStubStep(n.scope,{callId:stubCallId(e.session.id,e.session.turn.id,e.callId),tool:n.tool,input:e.input});if(t.kind===`error`)throw Error(t.error);if(t.kind===`stub`)return{output:toolStubOutput(t.outcome),status:`completed`}}let i=resolveWorkflowEntryPoint(e)(e.executeInput??e.input,t),a;if(!isAsyncIterable(i))a=await i;else{let t=i[Symbol.asyncIterator](),n,o=await t.next();for(;o.done!==!0;)n=o.value,await e.owner.send({from:r,kind:`report`,update:o.value}),o=await t.next();a=o.value??n}return{output:toWorkflowOutput(e,a),status:`completed`}}catch(e){return n.interrupted?{output:INTERRUPTED_OUTPUT,status:`completed`}:toFailedOutcome(e,n.runSignal)}}function toWorkflowOutput(e,t){return withToolOutputSerializationError({boundary:`execute`,toolCallId:e.callId,toolName:e.toolName},()=>parseJsonValue(t??null))}function toFailedOutcome(e,t){if(t.aborted){let{reason:e}=t;return{reason:e instanceof Error?e.message:String(e??``),status:`cancelled`}}return{error:normalizeSerializableError(e),status:`failed`}}function createWorkflowBodyRef(e){let t={callId:e.callId,input:e.input,runId:e.runId??getWorkflowMetadata().workflowRunId,sequence:e.session.turn.sequence,stepIndex:e.stepIndex,toolName:e.toolName,turnId:e.session.turn.id};return e.entry.entryPoint===`execute`?t:{...t,taskId:e.entry.taskId}}function resolveWorkflowEntryPoint(e){let t=readRegisteredWorkflow(e.workflowId);if(typeof t!=`function`)throw Error(`Tool "${e.toolName}" is not registered as a workflow in this deployment (${e.workflowId}). The tool was renamed or removed after this run started.`);return t}function createSharedContext(e,t,n){let unavailable=(t,n)=>{throw Error(`ctx.${t} is not available inside a workflow tool; ${n}. Tool "${e.toolName}" runs as a durable workflow body, which only replays deterministic code.`)};return{agent:t,ask:n,getSandbox:()=>unavailable(`getSandbox()`,`pass ctx directly to a "use step" helper to open the session's sandbox`),getToken:()=>unavailable(`getToken()`,`pass ctx directly to a "use step" helper to resolve credentials`),requireAuth:()=>unavailable(`requireAuth()`,`pass ctx directly to a "use step" helper to request authorization`),toolName:e.toolName}}function createAgentsView(e){return Object.freeze(Object.fromEntries(Object.entries(e.agents).map(([e,t])=>[e,Object.freeze({...t})])))}function createCallContext(e,t,n){let r={...createSharedContext(e,n,(e,t)=>ask(r,e,t)),abortSignal:t.abortSignal,agents:createAgentsView(e.agentContext),callId:e.callId,session:e.session};return r}function isAsyncIterable(e){return typeof e==`object`&&!!e&&typeof e[Symbol.asyncIterator]==`function`}var WorkflowToolRunCancelledError=class extends Error{constructor(e){super(e),this.name=`WorkflowToolRunCancelledError`}},WorkflowToolRunInterruptedError=class extends Error{constructor(){super(`A new message arrived while the turn waited on this call.`),this.name=`WorkflowToolRunInterruptedError`}};export{WorkflowToolRunCancelledError,WorkflowToolRunInterruptedError,createAgentsView,createSharedContext,createWorkflowBodyRef,resolveWorkflowEntryPoint,startCallBody,toFailedOutcome,toWorkflowOutput};
1
+ import{normalizeInstrumentationChannelKind}from"#shared/instrumentation-channel-kind.js";import{parseJsonValue}from"#shared/json.js";import{callToolStubStep}from"#execution/tool-stubs/steps.js";import{getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{toolStubOutput}from"#tool-stubs/output.js";import{createAgentSessions}from"#execution/agent-sessions/session.js";import{createRunUsageTally}from"#execution/agent-sessions/usage.js";import{WorkflowToolRunAsks,ask,attachWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{readRegisteredWorkflow}from"#execution/workflow-registry.js";import{withToolOutputSerializationError}from"#harness/tool-output-serialization.js";const INTERRUPTED_OUTPUT={interrupted:!0};var WorkflowCallSignals=class{body=new AbortController;run=new AbortController;asks;constructor(e){this.asks=e}get abortSignal(){return this.body.signal}get runSignal(){return this.run.signal}get interrupted(){return this.body.signal.aborted&&!this.run.signal.aborted}get unwinding(){return this.run.signal.aborted}apply(e){switch(e.kind){case`cancel`:case`end`:this.asks.cancelAll(),this.run.abort(new WorkflowToolRunCancelledError(e.reason)),this.body.abort(this.run.signal.reason);return;case`interrupt`:this.body.abort(new WorkflowToolRunInterruptedError);return;case`call`:return}}};function startCallBody(e){let t=createWorkflowBodyRef(e),n=new WorkflowToolRunAsks(t.runId),r=new WorkflowCallSignals(n),i={agentContext:e.agentContext,asks:n,auth:e.session.auth,control:e.hookToken,from:t,owner:e.owner},a=createRunUsageTally(),o=createAgentSessions(i,a),s=createCallContext(e,r,o.open);return attachWorkflowToolRunContext(s,i),{asks:n,close:o.close,control:r,outcome:executeCallBody(e,s,r,t),usage:a}}async function executeCallBody(e,t,n,r){try{let n=findStubTarget(e.agentContext.toolStubs,e.toolName);if(n!==void 0){let t=await callToolStubStep(n.scope,{callId:stubCallId(e.session.id,e.session.turn.id,e.callId),tool:n.tool,input:e.input});if(t.kind===`error`)throw Error(t.error);if(t.kind===`stub`)return{output:toolStubOutput(t.outcome),status:`completed`}}let i=resolveWorkflowEntryPoint(e)(e.executeInput??e.input,t),a;if(!isAsyncIterable(i))a=await i;else{let t=i[Symbol.asyncIterator](),n,o=await t.next();for(;o.done!==!0;)n=o.value,await e.owner.send({from:r,kind:`report`,update:o.value}),o=await t.next();a=o.value??n}return{output:toWorkflowOutput(e,a),status:`completed`}}catch(e){return n.interrupted?{output:INTERRUPTED_OUTPUT,status:`completed`}:toFailedOutcome(e,n.runSignal)}}function toWorkflowOutput(e,t){return withToolOutputSerializationError({boundary:`execute`,toolCallId:e.callId,toolName:e.toolName},()=>parseJsonValue(t??null))}function toFailedOutcome(e,t){if(t.aborted){let{reason:e}=t;return{reason:e instanceof Error?e.message:String(e??``),status:`cancelled`}}return{error:normalizeSerializableError(e),status:`failed`}}function createWorkflowBodyRef(e){let t={callId:e.callId,input:e.input,runId:e.runId??getWorkflowMetadata().workflowRunId,sequence:e.session.turn.sequence,stepIndex:e.stepIndex,toolName:e.toolName,turnId:e.session.turn.id};return e.entry.entryPoint===`execute`?t:{...t,taskId:e.entry.taskId}}function resolveWorkflowEntryPoint(e){let t=readRegisteredWorkflow(e.workflowId);if(typeof t!=`function`)throw Error(`Tool "${e.toolName}" is not registered as a workflow in this deployment (${e.workflowId}). The tool was renamed or removed after this run started.`);return t}function createSharedContext(e,t,n){let unavailable=(t,n)=>{throw Error(`ctx.${t} is not available inside a workflow tool; ${n}. Tool "${e.toolName}" runs as a durable workflow body, which only replays deterministic code.`)};return{agent:t,ask:n,getSandbox:()=>unavailable(`getSandbox()`,`pass ctx directly to a "use step" helper to open the session's sandbox`),getToken:()=>unavailable(`getToken()`,`pass ctx directly to a "use step" helper to resolve credentials`),requireAuth:()=>unavailable(`requireAuth()`,`pass ctx directly to a "use step" helper to request authorization`),to:()=>unavailable(`to()`,`pass ctx directly to a "use step" helper to send to a channel`),channel:workflowToolChannel(e.agentContext),toolName:e.toolName}}function workflowToolChannel(e){let t=e.channelMetadata;return{continuationToken:e.continuationToken,kind:normalizeInstrumentationChannelKind(t?.kind),metadata:t?.metadata??{}}}function createAgentsView(e){return Object.freeze(Object.fromEntries(Object.entries(e.agents).map(([e,t])=>[e,Object.freeze({...t})])))}function createCallContext(e,t,n){let r={...createSharedContext(e,n,(e,t)=>ask(r,e,t)),abortSignal:t.abortSignal,agents:createAgentsView(e.agentContext),callId:e.callId,session:e.session};return r}function isAsyncIterable(e){return typeof e==`object`&&!!e&&typeof e[Symbol.asyncIterator]==`function`}var WorkflowToolRunCancelledError=class extends Error{constructor(e){super(e),this.name=`WorkflowToolRunCancelledError`}},WorkflowToolRunInterruptedError=class extends Error{constructor(){super(`A new message arrived while the turn waited on this call.`),this.name=`WorkflowToolRunInterruptedError`}};export{WorkflowToolRunCancelledError,WorkflowToolRunInterruptedError,createAgentsView,createSharedContext,createWorkflowBodyRef,resolveWorkflowEntryPoint,startCallBody,toFailedOutcome,toWorkflowOutput,workflowToolChannel};
@@ -1,4 +1,5 @@
1
1
  import type { SessionContext } from "#context/session-context.js";
2
+ import type { InstrumentationChannel } from "#shared/instrumentation-channel.js";
2
3
  import type { AgentSessionBundle } from "#execution/agent-sessions/context.js";
3
4
  import type { AuthorizationResult, AuthorizationSignal } from "#harness/authorization.js";
4
5
  import type { SandboxState } from "#sandbox/state.js";
@@ -15,6 +16,10 @@ export interface WorkflowStepContext {
15
16
  readonly token: string;
16
17
  readonly authorizationResults: readonly WorkflowStepAuthorizationResult[];
17
18
  readonly sandbox: WorkflowStepSandbox;
19
+ /** Whether a parent, local or remote, delegated the calling session, which `ctx.to()` refuses. */
20
+ readonly delegated: boolean;
21
+ /** The calling session's channel, which `ctx.channel` holds. */
22
+ readonly channel: InstrumentationChannel;
18
23
  }
19
24
  /** Where `ctx.getSandbox()` finds the calling session's sandbox: its agent and sandbox key. */
20
25
  export interface WorkflowStepSandbox {