eve 0.81.0 → 0.82.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.
- package/CHANGELOG.md +37 -0
- package/dist/src/channel/channel-address.d.ts +21 -2
- package/dist/src/channel/channel-address.js +1 -1
- package/dist/src/channel/channel-operations.d.ts +32 -1
- package/dist/src/channel/channel-operations.js +1 -1
- package/dist/src/channel/delivery-idempotency.d.ts +4 -0
- package/dist/src/channel/delivery-idempotency.js +1 -0
- package/dist/src/channel/routes.d.ts +6 -0
- package/dist/src/channel/session.d.ts +5 -0
- package/dist/src/channel/session.js +1 -1
- package/dist/src/channel/types.d.ts +14 -11
- package/dist/src/chunks/{use-eve-agent-Bp6nbhfV.js → use-eve-agent-DTu78IAF.js} +36 -0
- package/dist/src/chunks/{use-eve-agent-DLkjJIm3.js → use-eve-agent-DlznYwQk.js} +36 -0
- package/dist/src/cli/dev/command-options.d.ts +1 -0
- package/dist/src/cli/dev/diagnostic-dump.js +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/message-reducer-types.d.ts +7 -3
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/transcript-reducer.d.ts +6 -3
- package/dist/src/client/transcript-reducer.js +1 -1
- package/dist/src/compiled/.vendor-stamp.json +2 -2
- package/dist/src/compiled/@eve/catalog/index.js +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +19 -18
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/load-binding-namespace.d.ts +2 -0
- package/dist/src/compiler/load-binding-namespace.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/module-lifecycle.d.ts +1 -1
- package/dist/src/compiler/module-lifecycle.js +1 -1
- package/dist/src/compiler/module-map.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/compiler/project-sources.d.ts +6 -0
- package/dist/src/compiler/project-sources.js +1 -1
- package/dist/src/context/keys.d.ts +2 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/evals/cli/eval-state-directory.d.ts +7 -0
- package/dist/src/evals/cli/eval-state-directory.js +1 -0
- package/dist/src/evals/cli/eval.js +2 -2
- package/dist/src/eve-channel/create-request.d.ts +2 -1
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/request.d.ts +2 -1
- package/dist/src/eve-channel/request.js +1 -2
- package/dist/src/eve-channel/support.d.ts +11 -1
- package/dist/src/eve-channel/support.js +2 -1
- package/dist/src/eve-channel/types.d.ts +25 -0
- package/dist/src/execution/agent-sessions/context.d.ts +2 -13
- package/dist/src/execution/agent-sessions/context.js +1 -1
- package/dist/src/execution/agent-sessions/runtime-overrides.d.ts +5 -0
- package/dist/src/execution/agent-sessions/runtime-overrides.js +1 -0
- package/dist/src/execution/agent-sessions/session.d.ts +2 -2
- package/dist/src/execution/agent-sessions/session.js +1 -1
- package/dist/src/execution/agent-sessions/steps.d.ts +2 -0
- package/dist/src/execution/agent-sessions/steps.js +1 -1
- package/dist/src/execution/coordination-dispatch-shared.d.ts +5 -5
- package/dist/src/execution/coordination-dispatch-step.d.ts +17 -2
- package/dist/src/execution/coordination-dispatch-step.js +1 -1
- package/dist/src/execution/create-session-step.d.ts +5 -2
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/deliver-payloads.js +1 -1
- package/dist/src/execution/durable-session-store.d.ts +0 -1
- package/dist/src/execution/dynamic-connection-recovery.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/effective-agent-config.d.ts +8 -2
- package/dist/src/execution/effective-agent-config.js +1 -1
- package/dist/src/execution/hook-ownership.d.ts +8 -0
- package/dist/src/execution/hook-ownership.js +1 -1
- package/dist/src/execution/install-workflow-deployment-id.d.ts +3 -0
- package/dist/src/execution/install-workflow-deployment-id.js +1 -0
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/node-step.d.ts +1 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/runtime-context.d.ts +2 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/admission.js +1 -1
- package/dist/src/execution/session/checkpoint-migrations.js +1 -1
- package/dist/src/execution/session/entry-input.d.ts +20 -8
- package/dist/src/execution/session/entry-input.js +1 -1
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/finalization.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +75 -13
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +73 -34
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/input-queue.d.ts +5 -1
- package/dist/src/execution/session/input-queue.js +1 -1
- package/dist/src/execution/session/pending-history.d.ts +5 -0
- package/dist/src/execution/session/pending-history.js +1 -0
- package/dist/src/execution/session/pending-turn-state.js +1 -1
- package/dist/src/execution/session/program.d.ts +1 -1
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/run-watch.d.ts +22 -0
- package/dist/src/execution/session/run-watch.js +1 -0
- package/dist/src/execution/session/timeout-control.d.ts +18 -4
- package/dist/src/execution/session/timeout-control.js +1 -1
- package/dist/src/execution/session/timeout.d.ts +1 -2
- package/dist/src/execution/session/timeout.js +1 -1
- package/dist/src/execution/session/turn-event-handler.js +1 -1
- package/dist/src/execution/session/turn-step-result.js +1 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn-waiting-step.js +1 -1
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-inbox/address.d.ts +4 -1
- package/dist/src/execution/session-inbox/end-stranded-session.js +1 -1
- package/dist/src/execution/session-inbox/hook-release.d.ts +9 -2
- package/dist/src/execution/session-inbox/hook-release.js +1 -1
- package/dist/src/execution/session-inbox/inbox.d.ts +66 -6
- package/dist/src/execution/session-inbox/inbox.js +1 -1
- package/dist/src/execution/session-inbox/protocol.js +1 -1
- package/dist/src/execution/session-inbox/resume.d.ts +4 -3
- package/dist/src/execution/session.d.ts +0 -12
- package/dist/src/execution/session.js +2 -2
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/model-step.js +1 -1
- package/dist/src/execution/tasks/start.d.ts +4 -4
- package/dist/src/execution/tasks/start.js +1 -1
- package/dist/src/execution/tasks/steps.js +1 -1
- package/dist/src/execution/terminate-child-sessions-step.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/workflow/body.d.ts +2 -2
- package/dist/src/execution/workflow-runtime.d.ts +11 -12
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/hitl/approvals.js +1 -1
- package/dist/src/harness/hitl/budget-request.d.ts +12 -6
- package/dist/src/harness/hitl/budget-request.js +1 -1
- package/dist/src/harness/hitl/budget.d.ts +7 -1
- package/dist/src/harness/hitl/budget.js +1 -1
- package/dist/src/harness/hitl/coordinator.js +1 -1
- package/dist/src/harness/hitl/delivery.d.ts +1 -1
- package/dist/src/harness/hitl/delivery.js +1 -1
- package/dist/src/harness/hitl/index.js +1 -1
- package/dist/src/harness/hitl/intake.d.ts +2 -2
- package/dist/src/harness/hitl/intake.js +1 -1
- package/dist/src/harness/messages.d.ts +5 -0
- package/dist/src/harness/messages.js +1 -1
- package/dist/src/harness/model-call/call.d.ts +2 -2
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/request.d.ts +2 -2
- package/dist/src/harness/session-machine/transitions.d.ts +3 -1
- package/dist/src/harness/session-machine/transitions.js +1 -1
- package/dist/src/harness/step/context.d.ts +3 -0
- package/dist/src/harness/step/context.js +1 -1
- package/dist/src/harness/step/intake.d.ts +5 -2
- package/dist/src/harness/step/intake.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +7 -26
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +10 -25
- package/dist/src/instrumentation/content.d.ts +1 -1
- package/dist/src/instrumentation/content.js +1 -1
- package/dist/src/instrumentation/lifecycle.d.ts +4 -2
- package/dist/src/internal/application/build-profile.d.ts +3 -0
- package/dist/src/internal/application/build-profile.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +2 -2
- package/dist/src/internal/application/dev-environment.d.ts +13 -0
- package/dist/src/internal/application/dev-environment.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/authored-module-build-options.d.ts +7 -0
- package/dist/src/internal/authored-module-build-options.js +1 -0
- package/dist/src/internal/authored-module-graph.d.ts +13 -0
- package/dist/src/internal/authored-module-graph.js +1 -0
- package/dist/src/internal/authored-module-loader.d.ts +22 -1
- package/dist/src/internal/authored-module-loader.js +1 -3
- package/dist/src/internal/authored-module.d.ts +7 -0
- package/dist/src/internal/authored-module.js +1 -1
- package/dist/src/internal/authored-package-boundary.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.d.ts +5 -1
- package/dist/src/internal/bundler/nitro-rolldown.js +1 -1
- package/dist/src/internal/development-programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/development-programmatic-source-loader.js +1 -1
- package/dist/src/internal/mcp/skills.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-generation-metadata.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/build-deployment-id.d.ts +8 -0
- package/dist/src/internal/nitro/host/build-deployment-id.js +1 -0
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-server-state.js +1 -1
- package/dist/src/internal/nitro/host/skill-server-assets.js +1 -1
- package/dist/src/internal/nitro/host/stage-build-deployment-id.d.ts +2 -0
- package/dist/src/internal/nitro/host/stage-build-deployment-id.js +1 -0
- package/dist/src/internal/nitro/host/start-production-server.d.ts +1 -0
- package/dist/src/internal/nitro/host/start-production-server.js +3 -3
- package/dist/src/internal/nitro/routes/schedule-task.d.ts +3 -0
- package/dist/src/internal/nitro/routes/schedule-task.js +1 -1
- package/dist/src/internal/programmatic-source-loader.d.ts +1 -0
- package/dist/src/internal/programmatic-source-loader.js +1 -1
- package/dist/src/internal/schedules/disabled.d.ts +2 -0
- package/dist/src/internal/schedules/disabled.js +1 -0
- package/dist/src/internal/workflow/development-world-client.js +1 -1
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/internal/workflow/local-world-data-directory.d.ts +2 -1
- package/dist/src/internal/workflow/local-world-data-directory.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +1 -1
- package/dist/src/protocol/message.d.ts +27 -1
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +13 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/chat-sdk/fetch-message.d.ts +10 -0
- package/dist/src/public/channels/chat-sdk/fetch-message.js +1 -0
- package/dist/src/public/channels/chat-sdk/index.d.ts +1 -1
- package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +2 -1
- package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -1
- package/dist/src/public/channels/chat-sdk/reply-context.d.ts +15 -0
- package/dist/src/public/channels/chat-sdk/reply-context.js +2 -0
- package/dist/src/public/channels/discord/discordChannel.d.ts +3 -0
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/github/dispatch.js +1 -1
- package/dist/src/public/channels/github/githubChannel.d.ts +3 -0
- package/dist/src/public/channels/imessage-tapbacks.d.ts +74 -0
- package/dist/src/public/channels/imessage-tapbacks.js +1 -0
- package/dist/src/public/channels/index.d.ts +2 -1
- package/dist/src/public/channels/index.js +1 -1
- package/dist/src/public/channels/linear/linearChannel.d.ts +3 -0
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linq/inboundContent.d.ts +7 -0
- package/dist/src/public/channels/linq/inboundContent.js +1 -1
- package/dist/src/public/channels/linq/index.d.ts +1 -0
- package/dist/src/public/channels/linq/index.js +1 -1
- package/dist/src/public/channels/linq/linqChannel.d.ts +17 -1
- package/dist/src/public/channels/linq/linqChannel.js +1 -1
- package/dist/src/public/channels/photon/attachments.d.ts +5 -2
- package/dist/src/public/channels/photon/attachments.js +1 -1
- package/dist/src/public/channels/photon/inboundContent.d.ts +7 -0
- package/dist/src/public/channels/photon/inboundContent.js +2 -1
- package/dist/src/public/channels/photon/index.d.ts +1 -0
- package/dist/src/public/channels/photon/index.js +1 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.d.ts +17 -1
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
- package/dist/src/public/channels/slack/api.d.ts +14 -1
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/channels/slack/model-context.d.ts +7 -0
- package/dist/src/public/channels/slack/model-context.js +1 -1
- package/dist/src/public/channels/slack/reply-delivery.d.ts +5 -0
- package/dist/src/public/channels/slack/reply-delivery.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.d.ts +17 -3
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -0
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/telegramChannel.d.ts +3 -0
- package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
- package/dist/src/public/definitions/agent.d.ts +1 -1
- package/dist/src/public/definitions/channel.d.ts +2 -2
- package/dist/src/public/definitions/channel.js +1 -1
- package/dist/src/public/definitions/hook.d.ts +1 -0
- package/dist/src/public/index.d.ts +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/runtime/agent/resolve-model.d.ts +4 -0
- package/dist/src/runtime/agent/resolve-model.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/sessions/compiled-agent-cache.js +1 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.d.ts +2 -1
- package/dist/src/runtime/subagents/dynamic-agent-config.js +1 -1
- package/dist/src/runtime/types.d.ts +3 -2
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +31 -42
- package/dist/src/shared/gateway-routing.d.ts +20 -0
- package/dist/src/shared/gateway-routing.js +1 -0
- package/dist/src/shared/session-history.d.ts +22 -0
- package/dist/src/shared/session-history.js +1 -0
- package/dist/src/shared/skill-package.js +1 -1
- package/dist/src/subagents/tool.d.ts +1 -3
- package/dist/src/subagents/tool.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tools/workflow-definition.d.ts +14 -1
- package/dist/src/tracing/eve/agent-otel-provider.js +1 -1
- package/dist/src/tracing/eve/conversation-context.d.ts +4 -1
- package/dist/src/tracing/eve/conversation-context.js +1 -1
- package/dist/src/tracing/eve/gateway.d.ts +5 -0
- package/dist/src/tracing/eve/gateway.js +1 -1
- package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
- package/dist/src/tracing/eve/operation-input.d.ts +0 -12
- package/dist/src/tracing/eve/operation-input.js +1 -1
- package/dist/src/tracing/eve/otel-registration.js +1 -1
- package/dist/src/tracing/eve/policy.d.ts +1 -1
- package/dist/src/tracing/eve/policy.js +1 -1
- package/dist/src/tracing/eve/session.d.ts +5 -2
- package/dist/src/tracing/eve/session.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/README.md +1 -0
- package/docs/agent-config.md +108 -65
- package/docs/channels/chat-sdk.mdx +10 -3
- package/docs/channels/custom.mdx +38 -6
- package/docs/channels/eve.mdx +73 -0
- package/docs/channels/linq.mdx +51 -0
- package/docs/channels/photon.mdx +68 -2
- package/docs/channels/slack.mdx +6 -2
- package/docs/concepts/built-in-tools.md +1 -1
- package/docs/concepts/execution-model-and-durability.mdx +27 -11
- package/docs/concepts/sessions-runs-and-streaming.md +9 -8
- package/docs/connections/overview.mdx +1 -1
- package/docs/experimental/dynamic-schedules.mdx +186 -0
- package/docs/experimental/meta.json +4 -0
- package/docs/guides/client/streaming.mdx +1 -0
- package/docs/guides/deployment/self-hosting.md +3 -0
- package/docs/guides/hooks.md +21 -1
- package/docs/guides/instrumentation/otel.mdx +20 -0
- package/docs/memory/overview.mdx +2 -1
- package/docs/patterns/dynamic-scheduling.md +3 -1
- package/docs/patterns/meta.json +1 -0
- package/docs/patterns/voice-notes.md +67 -0
- package/docs/reference/cli.md +14 -7
- package/docs/sandbox/index.mdx +2 -0
- package/docs/schedules.mdx +2 -0
- package/docs/subagents/index.mdx +2 -0
- package/docs/tools/overview.mdx +2 -1
- package/docs/tools/tasks-upgrade.md +12 -7
- package/docs/tools/tasks.md +10 -6
- package/docs/tools/workflows.mdx +36 -5
- package/docs/tutorial/connect-a-warehouse.mdx +1 -1
- package/docs/tutorial/run-analysis.mdx +1 -1
- package/package.json +1 -1
- package/dist/src/execution/run-session-limits.d.ts +0 -12
- package/dist/src/execution/run-session-limits.js +0 -1
- package/dist/src/harness/session-usage-limits.d.ts +0 -49
- package/dist/src/harness/session-usage-limits.js +0 -1
- package/dist/src/subagents/token-budget.d.ts +0 -15
- package/dist/src/subagents/token-budget.js +0 -1
|
@@ -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{getWorkflowMetadata,getWritable}from"#compiled/@workflow/core/index.js";import{isHookConflictError}from"#execution/hook-ownership.js";import{DEFAULT_SESSION_TIMEOUT_MS
|
|
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{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,stopUntrackedChildSessionsStep}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{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,r]=await Promise.allSettled([e.claimSessionHook(sessionCommandHookToken(t.sessionId)),t.continuationToken===``?Promise.resolve():e.claimSessionHook(t.continuationToken)]);if(n.status===`rejected`)throw n.reason;if(r.status===`rejected`){if(isHookConflictError(r.reason))return{kind:`alias-conflict`};throw r.reason}let i=createTurnControl(),a=createSessionTimeoutControl({sessionId:t.sessionId,timeoutMs:t.sessionTimeoutMs}),o={kind:`owned`,timeoutControl:a,turnControl:i,async dispose(){i.dispose(),await a?.dispose()}};return a?.start().catch(()=>{}),o}function unwrapSettled(e){if(e.status===`rejected`)throw e.reason;return e.value}async function disposeInitialBoot(e,t){let[n,r]=await Promise.allSettled([t?.dispose(),e.dispose()]);if(n.status===`rejected`)throw n.reason;if(r.status===`rejected`)throw r.reason}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`],c;try{let l=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}),u=prepareInitialOwner(i,{continuationToken:o,sessionId:t,sessionTimeoutMs:a}),d=hasDelegatedSessionContext(n)?resolveInitialTurnCallerStep({serializedContext:n}):Promise.resolve(void 0),[f,p,m]=await Promise.allSettled([l,u,d]);p.status===`fulfilled`&&p.value.kind===`owned`&&(c=p.value);let h=unwrapSettled(f),g=unwrapSettled(p);if(g.kind===`alias-conflict`){e.continuationConflictCommand!==void 0&&await settleContinuationConflictStep({command:e.continuationConflictCommand,continuationToken:o}),await disposeInitialBoot(i,c);return}let _=unwrapSettled(m);return{inbox:i,session:{admittedDeliveryKeys:e.idempotencyKey===void 0?[]:[e.idempotencyKey],anchor:{kind:`self`},caller:_,capabilities:n[`eve.capabilities`],deploymentId:e.ownerDeploymentId,history:h.history,start:e.input.message===void 0?{kind:`first-message`}:{input:createInitialDelivery(e,n),kind:`turn`},initialTurnControl:g.turnControl,retention:e.retention,serializedContext:n,sessionId:t,sessionState:h.state,sessionTimeoutControl:g.timeoutControl,sessionTimeoutMs:a,sessionWritable:r}}}catch(e){return await disposeInitialBoot(i,c),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,childRunIdsToStop:o}=r;return{checkpoint:a,childRunIdsToStop:o,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,childRunIdsToStop:a,serializedContext:o}=n;return a.length>0&&await stopUntrackedChildSessionsStep({runIds:a,sessionId:r}),{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?{kind:`parked`}:{input:e.delivery,kind:`turn`},retention:i.retention,serializedContext:o,sessionId:r,sessionState:i.sessionState,sessionTimeoutControl:createSessionTimeoutControl({sessionId:r,timeoutMs:i.sessionTimeoutMs}),sessionTimeoutMs:i.sessionTimeoutMs,sessionWritable:e.sessionWritable}}}function createInitialDelivery(e,t){if(e.input.message!==void 0)return{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 +1 @@
|
|
|
1
|
-
import{storedProjection}from"#harness/session-machine/view.js";import{
|
|
1
|
+
import{storedProjection}from"#harness/session-machine/view.js";import{getSessionUsage,takeSessionUsageDelta}from"#harness/turn-tag-state.js";import{liveTaskRuns,readTaskTable}from"#execution/tasks/table.js";import{terminateChildSessionsStep}from"#execution/terminate-child-sessions-step.js";import{notifyTurnCallerStep}from"#subagents/parent-notification.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{emitTerminalSessionCompletionStep}from"#execution/terminal-session-completion-step.js";import{endSessionSandboxStep,reportSessionSandboxCleanupFailureStep}from"#execution/session/end-sandbox-step.js";import{emitTerminalSessionFailureStep}from"#execution/terminal-session-failure-step.js";async function finalizeSession(e,t){let{serializedContext:n,sessionState:r}=t.cursor;if(r!==void 0&&liveTaskRuns(readTaskTable(r.snapshot?.session?.state)).length>0&&await terminateChildSessionsStep({sessionState:r}),r!==void 0)try{await endSessionSandboxStep({reason:e.kind===`done`?`completed`:e.kind,serializedContext:n,sessionState:r})}catch(t){await reportSessionSandboxCleanupFailureStep({error:normalizeSerializableError(t),outcome:e.kind,sessionId:r.sessionId}).catch(()=>void 0)}let i=r?.snapshot.session,a=i===void 0?void 0:getSessionUsage(i);e.kind===`expired`?await emitTerminalSessionCompletionStep({sessionWritable:t.sessionWritable,serializedContext:n,turn:lastPublishedTurn(i?.state),usage:a}):e.kind===`failed`&&await emitTerminalSessionFailureStep({error:normalizeSerializableError(e.error),sessionWritable:t.sessionWritable,serializedContext:n,turnId:e.turnId,usage:a});let o=settledResult(e,t);if(t.caller!==void 0){let e={output:o.output,usage:o.turnUsage};o.isError&&(e.isError=!0),await notifyTurnCallerStep({caller:t.caller,lifecycle:`terminal`,sessionId:r?.sessionId??n[`eve.sessionId`],settled:e})}return e.kind===`done`?{isError:e.action.isError,output:e.action.output,usage:e.action.usage,usageDelta:e.action.usageDelta}:{isError:o.isError,output:o.output,usage:o.sessionUsage,usageDelta:o.turnUsage}}function settledResult(e,t){let n=t.cursor.sessionState?.snapshot.session,r=n===void 0||t.caller===void 0?{}:{sessionUsage:getSessionUsage(n),turnUsage:takeSessionUsageDelta(n).delta};switch(e.kind){case`done`:return{isError:e.action.isError===!0,output:e.action.output,sessionUsage:e.action.usage,turnUsage:e.action.usageDelta};case`expired`:return t.caller===void 0?{isError:!1,output:``}:{isError:!0,output:`The session ended before the delegated task completed.`,...r};case`failed`:return{isError:!0,output:normalizeSerializableError(e.error),...r}}}function lastPublishedTurn(e){let t=Object.values(storedProjection(e).turns).reduce((e,t)=>e===void 0||t.sequence>e.sequence?t:e,void 0);return t===void 0?void 0:{id:t.turnId,sequence:t.sequence}}export{finalizeSession};
|
|
@@ -1,30 +1,68 @@
|
|
|
1
|
+
import type { SessionHandoverPayload } from "#execution/session-inbox/inbox.js";
|
|
1
2
|
import type { SessionCheckpointMigration } from "#execution/session/checkpoint-migrations.js";
|
|
2
3
|
import { type DurableSessionState } from "#execution/durable-session-store.js";
|
|
3
|
-
import { type SessionOwnerActivation } from "#execution/session/handoff.js";
|
|
4
|
+
import { type SessionCheckpoint, type SessionOwnerActivation } from "#execution/session/handoff.js";
|
|
5
|
+
import { type SessionHandoffStart } from "#execution/session/entry-input.js";
|
|
4
6
|
/** Parses retained work with this deployment's code before deciding whether it can move. */
|
|
5
7
|
export declare function isSessionStateIdleForHandoff(input: {
|
|
6
8
|
readonly sessionState: DurableSessionState;
|
|
7
9
|
}): boolean;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
export type SuccessorStartInput = SessionHandoffStart & {
|
|
11
|
+
readonly activationToken: string;
|
|
12
|
+
/** Original run whose stream stays the public session stream. */
|
|
13
|
+
readonly anchorRunId: string;
|
|
14
|
+
readonly attemptKey: string;
|
|
15
|
+
readonly checkpoint: SessionCheckpoint;
|
|
16
|
+
readonly hookTokens: readonly string[];
|
|
17
|
+
/** The owner starting the successor, which hands over what it accepts meanwhile. */
|
|
18
|
+
readonly sourceRunId: string;
|
|
19
|
+
readonly targetDeploymentId: string;
|
|
20
|
+
};
|
|
21
|
+
export type SuccessorStart = {
|
|
22
|
+
readonly kind: "not-idle";
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: "unsupported";
|
|
25
|
+
} | {
|
|
26
|
+
readonly kind: "started";
|
|
27
|
+
readonly runId: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Starts a successor owner bound to the original session stream, unless this
|
|
31
|
+
* deployment's code finds work in the checkpoint that cannot move yet, or the
|
|
32
|
+
* World cannot move session addresses between runs without releasing them.
|
|
33
|
+
*/
|
|
34
|
+
export declare function startSuccessorStep(input: SuccessorStartInput): Promise<SuccessorStart>;
|
|
35
|
+
/** Whether `runId` has ended; a run not readable yet has not. */
|
|
36
|
+
export declare function hasRunEndedStep(input: {
|
|
37
|
+
readonly runId: string;
|
|
11
38
|
}): Promise<boolean>;
|
|
12
39
|
export type SessionCheckpointValidation = {
|
|
13
40
|
readonly kind: "valid";
|
|
14
41
|
} | {
|
|
15
42
|
readonly kind: "incompatible";
|
|
16
43
|
readonly reason: "checkpoint-version";
|
|
44
|
+
}
|
|
45
|
+
/** The source no longer holds every address it handed over, so none may be taken. */
|
|
46
|
+
| {
|
|
47
|
+
readonly kind: "source-gone";
|
|
17
48
|
};
|
|
18
49
|
/**
|
|
19
|
-
* Validates an upgraded checkpoint
|
|
20
|
-
*
|
|
50
|
+
* Validates an upgraded checkpoint, resolves the target deployment's compiled
|
|
51
|
+
* bundle, and records this owner's identity before it claims any hook.
|
|
21
52
|
*
|
|
22
53
|
* A checkpoint this deployment cannot read is a settled answer, not a fault,
|
|
23
54
|
* so it returns rather than throws: retrying the step can never change it.
|
|
24
55
|
*/
|
|
25
|
-
export declare function
|
|
56
|
+
export declare function prepareSuccessorStep(input: {
|
|
57
|
+
/** Absent for version 1 sources, which predate the field. */
|
|
58
|
+
readonly handoffVersion: number | undefined;
|
|
26
59
|
readonly migration: SessionCheckpointMigration;
|
|
27
60
|
readonly sessionId: string;
|
|
61
|
+
/** Version 3: the run that still holds the session and the addresses it hands over. */
|
|
62
|
+
readonly source?: {
|
|
63
|
+
readonly runId: string;
|
|
64
|
+
readonly hookTokens: readonly string[];
|
|
65
|
+
};
|
|
28
66
|
}): Promise<SessionCheckpointValidation>;
|
|
29
67
|
/**
|
|
30
68
|
* Stops idle subagent sessions an older owner kept resumable, after this owner
|
|
@@ -43,12 +81,12 @@ export declare function reportSessionHandoffRetainedStep(input: {
|
|
|
43
81
|
readonly targetDeploymentId: string;
|
|
44
82
|
}): Promise<void>;
|
|
45
83
|
/**
|
|
46
|
-
* Records the identity of
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
84
|
+
* Records the identity of a legacy importer before it claims any hook;
|
|
85
|
+
* handoff successors do the same inside `prepareSuccessorStep`. Ingress reads
|
|
86
|
+
* `$eve.version` to decide whether the owner can run, so a missing value would
|
|
87
|
+
* strand a healthy session. The value comes from this step's code, not the
|
|
88
|
+
* previous owner's. Unlike observability attributes, a failed write fails the
|
|
89
|
+
* boot.
|
|
52
90
|
*/
|
|
53
91
|
export declare function recordSessionOwnerStep(input: {
|
|
54
92
|
readonly sessionId: string;
|
|
@@ -57,6 +95,30 @@ export declare function signalSessionOwnerActivationStep(input: {
|
|
|
57
95
|
readonly activation: SessionOwnerActivation;
|
|
58
96
|
readonly token: string;
|
|
59
97
|
}): Promise<void>;
|
|
98
|
+
/** Makes a takeover with no attempt open visible: every forced claim belongs to one. */
|
|
99
|
+
export declare function reportSessionTakenOverOutsideAttemptStep(input: {
|
|
100
|
+
readonly sessionId: string;
|
|
101
|
+
}): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Makes a move whose handover part keeps failing visible; the owner keeps
|
|
104
|
+
* retrying, because dropping the part would lose an accepted message.
|
|
105
|
+
*/
|
|
106
|
+
export declare function reportHandoverPartStuckStep(input: {
|
|
107
|
+
readonly attemptKey: string;
|
|
108
|
+
readonly error: string | undefined;
|
|
109
|
+
readonly failures: number;
|
|
110
|
+
readonly index: number;
|
|
111
|
+
readonly sessionId: string;
|
|
112
|
+
}): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Sends one handover part through the stable session address, which reaches
|
|
115
|
+
* whichever run owns the session. A part that keeps failing fails the step,
|
|
116
|
+
* for the caller to retry until it is delivered.
|
|
117
|
+
*/
|
|
118
|
+
export declare function sendSessionHandoverPartStep(input: {
|
|
119
|
+
readonly part: Omit<SessionHandoverPayload, "kind">;
|
|
120
|
+
readonly sessionId: string;
|
|
121
|
+
}): Promise<"delivered" | "session-ended">;
|
|
60
122
|
export declare function signalSessionAnchorStep(input: {
|
|
61
123
|
readonly result: {
|
|
62
124
|
readonly output: unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openInputs,openSignIns}from"#protocol/session-projection.js";import{createLogger,logError}from"#internal/logging.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{getSandboxEnvironmentRuntime}from"#shared/sandbox-environment.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{queuedInput,storedProjection}from"#harness/session-machine/view.js";import{cancelRun,getWorld,resumeHook}from"#internal/workflow/runtime.js";import{getResolvedRuntimeAgentNode}from"#runtime/graph.js";import{readDurableSession}from"#execution/durable-session-store.js";import{getBlockingWorkflowToolRuns}from"#harness/workflow-tool-runs.js";import{IncompatibleStateLayoutError,deserializeContext}from"#context/serialize.js";import{holdsHitlRequests}from"#harness/hitl/index.js";import{EntityConflictError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{EVE_SESSION_ATTRIBUTE,EVE_VERSION_ATTRIBUTE}from"#execution/eve-workflow-attributes.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";const log=createLogger(`execution.handoff`);function isSessionStateIdleForHandoff(e){let{state:t}=readDurableSession(e.sessionState),n=getBlockingWorkflowToolRuns(t);if(holdsHitlRequests(t)||[`eve.runtime.pendingInputBatch`,`eve.runtime.pendingCoordinationBatch`,`eve.runtime.deferredStepInput`,`eve.harness.pendingWorkflowInterrupt`].some(e=>t?.[e]!==void 0))return!1;let r=t?.[`eve.runtime.pendingInputBatches`];if(r!==void 0&&(!Array.isArray(r)||r.length>0))return!1;let i=storedProjection(t);return n.length===0&&i.activeTurnId===void 0&&openInputs(i).length===0&&openSignIns(i).length===0&&queuedInput(t)===void 0}async function
|
|
1
|
+
import{openInputs,openSignIns}from"#protocol/session-projection.js";import{createLogger,logError}from"#internal/logging.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{getSandboxEnvironmentRuntime}from"#shared/sandbox-environment.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{queuedInput,storedProjection}from"#harness/session-machine/view.js";import{cancelRun,getRun,getWorld,resumeHook}from"#internal/workflow/runtime.js";import{hasRunEnded,startWorkflowOnDeployment,workflowEntryReference}from"#execution/workflow-runtime.js";import{getResolvedRuntimeAgentNode}from"#runtime/graph.js";import{readDurableSession}from"#execution/durable-session-store.js";import{getBlockingWorkflowToolRuns}from"#harness/workflow-tool-runs.js";import{IncompatibleStateLayoutError,deserializeContext}from"#context/serialize.js";import{holdsHitlRequests}from"#harness/hitl/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{findSessionHookHolder}from"#execution/session-inbox/owner.js";import{EVE_SESSION_ATTRIBUTE,EVE_VERSION_ATTRIBUTE}from"#execution/eve-workflow-attributes.js";import{SESSION_CHECKPOINT_VERSION}from"#execution/session/handoff.js";import{mapWithConcurrency}from"#shared/map-with-concurrency.js";import{SESSION_HANDOFF_VERSION}from"#execution/session/entry-input.js";const log=createLogger(`execution.handoff`);function isSessionStateIdleForHandoff(e){let{state:t}=readDurableSession(e.sessionState),n=getBlockingWorkflowToolRuns(t);if(holdsHitlRequests(t)||[`eve.runtime.pendingInputBatch`,`eve.runtime.pendingCoordinationBatch`,`eve.runtime.deferredStepInput`,`eve.harness.pendingWorkflowInterrupt`].some(e=>t?.[e]!==void 0))return!1;let r=t?.[`eve.runtime.pendingInputBatches`];if(r!==void 0&&(!Array.isArray(r)||r.length>0))return!1;let i=storedProjection(t);return n.length===0&&i.activeTurnId===void 0&&openInputs(i).length===0&&openSignIns(i).length===0&&queuedInput(t)===void 0}async function startSuccessorStep(e){"use step";let{activationToken:t,anchorRunId:n,checkpoint:r,targetDeploymentId:i,...a}=e,{capabilities:o}=await getWorld();if(o?.hookForceClaim!==!0||o.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 s={...a,activationToken:t,checkpoint:r,handoffVersion:SESSION_HANDOFF_VERSION,kind:`handoff`,ownerDeploymentId:i,sessionWritable:getRun(n).getWritable(),sessionId:n};return{kind:`started`,runId:(await startWorkflowOnDeployment(workflowEntryReference,[s],i,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&&o.providerName!==void 0){let e=getResolvedRuntimeAgentNode(a.graph,a.nodeId).sandboxRegistry.sandbox.inheritance?.definition??getResolvedRuntimeAgentNode(a.graph,a.nodeId).sandboxRegistry.sandbox.definition;if(e.kind!==`independent`)throw Error(`Session checkpoint sandbox has no resolved provider.`);let t=getSandboxEnvironmentRuntime(e.environment);if(o.providerName!==t.providerName||o.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 stopUntrackedChildSessionsStep(e){"use step";let t=await getWorld();for(let n of e.runIds)if(n!==e.sessionId)try{await cancelRun(t,n,{cancelReason:`Session upgraded`})}catch(t){[...walkCauseChain(t)].some(e=>EntityConflictError.is(e)||RunExpiredError.is(e)||WorkflowRunNotFoundError.is(e))||logError(log,`could not stop a subagent session after handoff`,t,{childRunId:n,sessionId:e.sessionId})}}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_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";try{return await resumeHook(sessionInboxHookToken(sessionCommandHookToken(e.sessionId)),{...e.part,kind:`handover`}),`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,isSessionStateIdleForHandoff,prepareSuccessorStep,recordSessionOwnerStep,reportHandoverPartStuckStep,reportSessionHandoffRetainedStep,reportSessionTakenOverOutsideAttemptStep,sendSessionHandoverPartStep,signalSessionAnchorStep,signalSessionOwnerActivationStep,startSuccessorStep,stopUntrackedChildSessionsStep};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SessionCapabilities } from "#channel/types.js";
|
|
2
2
|
import type { DurableSessionState } from "#execution/durable-session-store.js";
|
|
3
3
|
import type { HarnessModelMessage } from "#harness/messages.js";
|
|
4
4
|
import type { SessionInboxHandle, SessionInboxPayload } from "#execution/session-inbox/inbox.js";
|
|
@@ -13,9 +13,10 @@ import type { AgentWorkflowRetentionDefinition } from "#shared/agent-definition.
|
|
|
13
13
|
* A newer successor must always accept older checkpoints: every bump adds the
|
|
14
14
|
* upgrade from the previous version in `checkpoint-migrations.ts`.
|
|
15
15
|
*/
|
|
16
|
-
export declare const SESSION_CHECKPOINT_VERSION =
|
|
16
|
+
export declare const SESSION_CHECKPOINT_VERSION = 16;
|
|
17
17
|
/** Everything a successor needs to continue an idle session. Hooks are derived from the state. */
|
|
18
18
|
export interface SessionCheckpoint {
|
|
19
|
+
readonly admittedDeliveryKeys: readonly string[];
|
|
19
20
|
readonly version: typeof SESSION_CHECKPOINT_VERSION;
|
|
20
21
|
readonly capabilities?: SessionCapabilities;
|
|
21
22
|
readonly history: HarnessModelMessage[];
|
|
@@ -29,81 +30,119 @@ export type SessionOwnerActivation = {
|
|
|
29
30
|
} | {
|
|
30
31
|
readonly kind: "incompatible";
|
|
31
32
|
readonly reason: "checkpoint-version";
|
|
33
|
+
/** Version 3: the successor run that gave this verdict. */
|
|
34
|
+
readonly runId?: string;
|
|
32
35
|
/** Commands accepted by partial successor claims before it rejected the checkpoint. */
|
|
33
36
|
readonly payloads: readonly SessionInboxPayload[];
|
|
34
37
|
} | {
|
|
35
38
|
readonly kind: "failed";
|
|
39
|
+
/**
|
|
40
|
+
* Version 3: the successor took some of the session's hooks before it
|
|
41
|
+
* failed. The owner takes them back and waits for their handover.
|
|
42
|
+
*/
|
|
43
|
+
readonly claimedHooks?: boolean;
|
|
36
44
|
readonly error: unknown;
|
|
45
|
+
/** Version 3: the successor run that gave this verdict. */
|
|
46
|
+
readonly runId?: string;
|
|
37
47
|
/** Commands accepted by partial successor claims before startup failed. */
|
|
38
48
|
readonly payloads: readonly SessionInboxPayload[];
|
|
39
49
|
};
|
|
40
50
|
interface SessionHandoffInput {
|
|
41
|
-
readonly checkpoint: Omit<SessionCheckpoint, "history" | "serializedContext" | "sessionState" | "version">;
|
|
51
|
+
readonly checkpoint: Omit<SessionCheckpoint, "admittedDeliveryKeys" | "history" | "serializedContext" | "sessionState" | "version">;
|
|
42
52
|
readonly deploymentId: string;
|
|
43
53
|
readonly inbox: SessionInboxHandle;
|
|
44
54
|
readonly isInitialOwner: boolean;
|
|
45
55
|
readonly sessionId: string;
|
|
46
56
|
}
|
|
47
57
|
export declare function sessionAnchorToken(sessionId: string): string;
|
|
58
|
+
/** Only one run per attempt can hold this; a successor that loses it exits untouched. */
|
|
59
|
+
export declare function handoffLeaseToken(attemptKey: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Measured from the lease's creation and far beyond any queue delay, so a
|
|
62
|
+
* duplicate candidate that boots late still finds the token taken.
|
|
63
|
+
*/
|
|
64
|
+
export declare const HANDOFF_LEASE_RETENTION = "7d";
|
|
48
65
|
type SessionTransferOutcome = {
|
|
49
66
|
readonly kind: "transferred";
|
|
50
67
|
} | {
|
|
51
68
|
readonly kind: "retained";
|
|
52
69
|
readonly reason: SessionRetainedReason;
|
|
53
70
|
};
|
|
54
|
-
type SessionRetainedReason = "same-deployment" | "missing-deployment" | "not-idle" | "busy" | "
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
type SessionRetainedReason = "same-deployment" | "missing-deployment" | "not-idle" | "busy" | "activation-failed" | "checkpoint-incompatible" | "known-incompatible" | "unsupported-world";
|
|
72
|
+
type SessionTransferState = Pick<SessionCheckpoint, "admittedDeliveryKeys" | "history" | "serializedContext" | "sessionState">;
|
|
73
|
+
/**
|
|
74
|
+
* Sends `payloads` as handover parts, one payload per part: each was accepted
|
|
75
|
+
* on its own, so no part exceeds what the World already took. Every part is
|
|
76
|
+
* retried with backoff until it is delivered or the session has ended: the
|
|
77
|
+
* receiver reads nothing until the final part lands, and dropping a part
|
|
78
|
+
* would lose a message the session accepted.
|
|
79
|
+
*/
|
|
80
|
+
export declare function sendSessionHandover(input: {
|
|
81
|
+
readonly attemptKey: string;
|
|
82
|
+
readonly payloads: readonly SessionInboxPayload[];
|
|
83
|
+
readonly sessionId: string;
|
|
84
|
+
}): Promise<void>;
|
|
60
85
|
/**
|
|
61
86
|
* The sole boundary for moving an idle session to a successor run: on another
|
|
62
87
|
* exact deployment when newer code accepts a delivery, or on this deployment
|
|
63
88
|
* after compaction so no single run's event log grows with the session.
|
|
64
89
|
* Constructed once per owner; each `try*` method attempts one transfer.
|
|
65
|
-
* When the upstream atomic hook-handoff primitive lands, only this class changes.
|
|
66
90
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* retries.
|
|
91
|
+
* The owner never releases its hooks. The successor force-claims every one of
|
|
92
|
+
* them, and the takeover itself is the success signal: the owner then hands
|
|
93
|
+
* over whatever it accepted meanwhile and exits. Until the attempt settles
|
|
94
|
+
* the owner runs no turn.
|
|
72
95
|
*/
|
|
73
96
|
export declare class SessionHandoff {
|
|
74
97
|
private readonly input;
|
|
75
98
|
private anchor;
|
|
76
99
|
/** Deployments that rejected this session's checkpoint during this owner run. */
|
|
77
100
|
private readonly incompatibleTargetDeploymentIds;
|
|
101
|
+
/** Counts this run's attempts; replay repeats the same sequence. */
|
|
102
|
+
private attempts;
|
|
103
|
+
/** The World cannot force-claim hooks, so no attempt can ever succeed. */
|
|
104
|
+
private worldUnsupported;
|
|
78
105
|
constructor(input: SessionHandoffInput);
|
|
79
106
|
/**
|
|
80
|
-
* Attempts to move the session to the selected delivery's deployment.
|
|
81
|
-
*
|
|
82
|
-
* session
|
|
83
|
-
* successor activated or this owner retained the session. Candidate failures
|
|
84
|
-
* recover locally rather than escaping.
|
|
107
|
+
* Attempts to move the session to the selected delivery's deployment. The
|
|
108
|
+
* outcome states whether the successor took over or this owner retained the
|
|
109
|
+
* session. Candidate failures recover locally rather than escaping.
|
|
85
110
|
*/
|
|
86
|
-
tryTransfer(selection: TurnSelection, state: SessionTransferState
|
|
87
|
-
readonly compaction?: CompactionHandoff;
|
|
88
|
-
}): Promise<SessionTransferOutcome>;
|
|
111
|
+
tryTransfer(selection: TurnSelection, state: SessionTransferState): Promise<SessionTransferOutcome>;
|
|
89
112
|
/**
|
|
90
113
|
* Attempts to move a session that compacted to a fresh run on this
|
|
91
|
-
* deployment.
|
|
92
|
-
*
|
|
93
|
-
* the session's deadline.
|
|
114
|
+
* deployment. The caller guarantees no input is waiting; the successor
|
|
115
|
+
* parks until the next one arrives.
|
|
94
116
|
*/
|
|
95
|
-
tryCompactionTransfer(state: SessionTransferState
|
|
96
|
-
readonly delivery?: DeliverHookPayload;
|
|
97
|
-
}): Promise<SessionTransferOutcome>;
|
|
117
|
+
tryCompactionTransfer(state: SessionTransferState): Promise<SessionTransferOutcome>;
|
|
98
118
|
private transfer;
|
|
119
|
+
/**
|
|
120
|
+
* The session was taken over while no attempt was open. This run leaves as
|
|
121
|
+
* after a transfer, without finalizing the stream the new owner now writes.
|
|
122
|
+
*/
|
|
123
|
+
adoptTakeover(): Promise<{
|
|
124
|
+
readonly kind: "transferred";
|
|
125
|
+
}>;
|
|
126
|
+
/**
|
|
127
|
+
* Claims the attempt's lease. `gaveUpRunId` is the candidate whose outcome
|
|
128
|
+
* the owner is acting on: holding the lease, it can no longer take over.
|
|
129
|
+
*/
|
|
130
|
+
private fenceAttempt;
|
|
131
|
+
/** Forwards what this run accepted but never read to the run that took the session over. */
|
|
132
|
+
private handOver;
|
|
133
|
+
/**
|
|
134
|
+
* Takes back every address a candidate that gave up may hold. Forced claims
|
|
135
|
+
* replace this run's own hooks, so this holds whether or not a pump has
|
|
136
|
+
* observed the candidate's claim yet.
|
|
137
|
+
*/
|
|
138
|
+
private holdEveryToken;
|
|
139
|
+
private recoverFromSilentCandidate;
|
|
140
|
+
/** Keeps the session after a candidate's verdict, taking back any hook it claimed. */
|
|
141
|
+
private recover;
|
|
142
|
+
private ensureAnchor;
|
|
99
143
|
/** After a transfer, the original run parks until the final owner reports the session result. */
|
|
100
144
|
awaitAnchoredResult(): Promise<WorkflowEntryResult>;
|
|
101
145
|
disposeAnchor(): Promise<void>;
|
|
102
|
-
/** Starts the candidate and waits for it to activate or fail. */
|
|
103
|
-
private startAndActivate;
|
|
104
|
-
/** Reclaims the exact hook set and replays payloads accepted while it was released. */
|
|
105
|
-
private recover;
|
|
106
146
|
private reportRetained;
|
|
107
|
-
private ensureAnchor;
|
|
108
147
|
}
|
|
109
148
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{createHook,getWorkflowMetadata,sleep}from"#compiled/@workflow/core/index.js";import{claimHookOwnership,disposeHook,isHookConflictError}from"#execution/hook-ownership.js";import{hasRunEndedStep,reportHandoverPartStuckStep,reportSessionHandoffRetainedStep,reportSessionTakenOverOutsideAttemptStep,sendSessionHandoverPartStep,startSuccessorStep}from"#execution/session/handoff-steps.js";import{abandonHandoverIfRunEnds,watchRunEnd}from"#execution/session/run-watch.js";import{readAcceptedDeploymentId}from"#execution/session/accepted-deployment.js";const SESSION_CHECKPOINT_VERSION=16;function sessionAnchorToken(e){return`${e}:anchor`}function handoffLeaseToken(e){return`eve:handoff:lease:${e}`}const HANDOFF_LEASE_RETENTION=`7d`;function verdictRunId(e){return e.kind===`verdict`&&e.verdict.kind!==`active`?e.verdict.runId:void 0}async function sendSessionHandover(e){let{attemptKey:t,sessionId:n}=e,r=e.payloads.filter(e=>e.kind!==`handover`);for(let[e,i]of r.entries())if(await sendHandoverPart({attemptKey:t,index:e,payloads:[i]},n)===`session-ended`)return;await sendHandoverPart({attemptKey:t,final:!0,index:r.length,payloads:[]},n)}async function sendHandoverPart(e,t){for(let n=1,r=1;;n++)try{return await sendSessionHandoverPartStep({part:e,sessionId:t})}catch(i){n===HANDOVER_PART_FAILURES_BEFORE_REPORT&&await reportHandoverPartStuckStep({attemptKey:e.attemptKey,error:isObject(i)&&typeof i.message==`string`?i.message:void 0,failures:n,index:e.index,sessionId:t}).catch(()=>{}),await sleep(r*1e3),r=Math.min(r*2,60)}}const HANDOVER_PART_FAILURES_BEFORE_REPORT=5;var SessionHandoff=class{input;anchor;incompatibleTargetDeploymentIds=new Set;attempts=0;worldUnsupported=!1;constructor(e){this.input=e}async tryTransfer(e,t){let{delivery:n}=e,r=readAcceptedDeploymentId(n);return r===void 0?{kind:`retained`,reason:`missing-deployment`}:r===this.input.deploymentId?{kind:`retained`,reason:`same-deployment`}:this.incompatibleTargetDeploymentIds.has(r)?{kind:`retained`,reason:`known-incompatible`}:e.handoffEligible?await this.transfer(t,r,{delivery:n}):{kind:`retained`,reason:`busy`}}async tryCompactionTransfer(e){let{deploymentId:t}=this.input;return this.incompatibleTargetDeploymentIds.has(t)?{kind:`retained`,reason:`known-incompatible`}:await this.transfer(e,t,{reason:`compaction`})}async transfer(e,t,n){let{inbox:r}=this.input;if(this.worldUnsupported)return{kind:`retained`,reason:`unsupported-world`};if(r.awaitingHandover)return{kind:`retained`,reason:`busy`};let i=getWorkflowMetadata().workflowRunId,a=this.attempts++,o=`${i}:${String(a)}`,s=r.claimedTokens,c=createHook({token:`${i}:handoff:${String(a)}`});this.ensureAnchor();let l=new AbortController,u=Date.now();try{let a;try{let r=await startSuccessorStep({...n,activationToken:c.token,anchorRunId:this.input.sessionId,attemptKey:o,checkpoint:{...this.input.checkpoint,...e,version:16},hookTokens:s,sourceRunId:i,targetDeploymentId:t});if(r.kind===`not-idle`)return{kind:`retained`,reason:`not-idle`};if(r.kind===`unsupported`)return this.worldUnsupported=!0,{kind:`retained`,reason:`unsupported-world`};a=r.runId}catch(e){let n=await this.fenceAttempt(o);if(n.kind!==`live`)return n.kind===`done`&&await this.holdEveryToken(s),await this.reportRetained(`activation-failed`,t,e),{kind:`retained`,reason:`activation-failed`};a=n.runId}let d=r.whenTakenOver(l.signal).then(()=>({kind:`taken-over`})),f,p;for(;;){if(f===void 0&&p===void 0&&r.hasPending()){let e=u+3e5-Date.now();p=sleep(Math.max(0,e)).then(()=>({kind:`deadline`}))}let e;try{e=await Promise.race([d,c.then(e=>({kind:`verdict`,verdict:e})),f===void 0?p??r.whenArrival().then(()=>({kind:`arrival`})):f.ended.then(()=>({kind:`candidate-ended`}))])}finally{f?.stop()}if(e.kind===`taken-over`)return await this.handOver(o);if(e.kind===`arrival`)continue;let n=e.kind===`candidate-ended`?a:verdictRunId(e),i=await this.fenceAttempt(o,n);if(i.kind===`live`){a=i.runId,f=watchRunEnd(a);continue}i.kind===`done`&&i.runId!==verdictRunId(e)&&await this.holdEveryToken(s);let l=e.kind===`verdict`?await this.recover(e.verdict,{attemptKey:o,candidateRunId:a,hookTokens:s,targetDeploymentId:t}):this.recoverFromSilentCandidate(e.kind);return await this.reportRetained(l.reason,t,l.error),{kind:`retained`,reason:l.reason}}}finally{l.abort(),await disposeHook(c)}}async adoptTakeover(){return await reportSessionTakenOverOutsideAttemptStep({sessionId:this.input.sessionId}),this.ensureAnchor(),{kind:`transferred`}}async fenceAttempt(e,t){let n=createHook({experimental_minRetention:`7d`,token:handoffLeaseToken(e)});try{await claimHookOwnership(n)}catch(e){if(!isHookConflictError(e)||typeof e.conflictingRunId!=`string`)throw e;let n=e.conflictingRunId;return n===t||await hasRunEndedStep({runId:n})?{kind:`done`,runId:n}:{kind:`live`,runId:n}}return{kind:`won`}}async handOver(e){return await sendSessionHandover({attemptKey:e,payloads:this.input.inbox.drain(),sessionId:this.input.sessionId}),{kind:`transferred`}}async holdEveryToken(e){await this.input.inbox.claimSessionHooks(e,{force:!0})}recoverFromSilentCandidate(e){return{error:Error(e===`deadline`?`The successor run did not report within 5 minutes.`:`The successor run ended before the handoff settled.`),reason:`activation-failed`}}async recover(e,t){let{inbox:n}=this.input;switch(e.kind){case`active`:return{error:Error(`Successor reported active without a takeover.`),reason:`activation-failed`};case`incompatible`:return this.incompatibleTargetDeploymentIds.add(t.targetDeploymentId),e.payloads.length>0&&n.restore(e.payloads),{reason:`checkpoint-incompatible`};case`failed`:return e.claimedHooks===!0?(await n.claimSessionHooks(t.hookTokens,{force:!0,handover:t.attemptKey}),abandonHandoverIfRunEnds(n,{attemptKey:t.attemptKey,sourceRunId:e.runId??t.candidateRunId})):isHookConflictError(e.error)&&this.incompatibleTargetDeploymentIds.add(t.targetDeploymentId),e.payloads.length>0&&n.restore(e.payloads),{error:e.error,reason:`activation-failed`}}}ensureAnchor(){this.input.isInitialOwner&&this.anchor===void 0&&(this.anchor=createHook({token:sessionAnchorToken(this.input.sessionId)}))}async awaitAnchoredResult(){if(this.anchor===void 0)throw Error(`Session anchor was never claimed.`);try{return await this.anchor}finally{await this.disposeAnchor()}}async disposeAnchor(){if(this.anchor===void 0)return;let e=this.anchor;this.anchor=void 0,await disposeHook(e)}async reportRetained(e,t,n){let r=isObject(n)&&typeof n.message==`string`?n.message:void 0;await reportSessionHandoffRetainedStep({error:r,reason:e,sessionId:this.input.sessionId,sourceDeploymentId:this.input.deploymentId,targetDeploymentId:t})}};export{HANDOFF_LEASE_RETENTION,SESSION_CHECKPOINT_VERSION,SessionHandoff,handoffLeaseToken,sendSessionHandover,sessionAnchorToken};
|
|
@@ -27,11 +27,15 @@ export type SessionInputSelection = TurnSelection | {
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class SessionInputQueue {
|
|
29
29
|
private readonly entries;
|
|
30
|
+
private readonly admittedKeys;
|
|
30
31
|
private nextSequence;
|
|
32
|
+
constructor(admittedDeliveryKeys: readonly string[]);
|
|
33
|
+
get admittedDeliveryKeys(): readonly string[];
|
|
34
|
+
isDuplicate(delivery: DeliverHookPayload): boolean;
|
|
31
35
|
get pendingCount(): number;
|
|
32
36
|
/** The sequence the next admission receives; every earlier admission is below it. */
|
|
33
37
|
get nextAdmission(): number;
|
|
34
|
-
enqueueDelivery(delivery: DeliverHookPayload): DeliveryAdmission;
|
|
38
|
+
enqueueDelivery(delivery: DeliverHookPayload): DeliveryAdmission | undefined;
|
|
35
39
|
enqueueControl(control: SessionControl): void;
|
|
36
40
|
/** Keeps one payload per authorization attempt; a repeated callback for the same attempt is dropped. */
|
|
37
41
|
enqueueAuthorization(payloads: readonly DeliverPayload[]): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{coalesceDeliveries}from"#harness/messages.js";import{ANONYMOUS_PRINCIPAL,principalOf}from"#execution/session/principal.js";var SessionInputQueue=class{entries=[];nextSequence=0;get pendingCount(){return this.entries.length}get nextAdmission(){return this.nextSequence}enqueueDelivery(e){let t={delivery:e,sequence:this.nextSequence++};return this.entries.push({...t,kind:`delivery`}),t}enqueueControl(e){this.entries.push({control:e,kind:`control`,sequence:this.nextSequence++})}enqueueAuthorization(e){for(let t of e){let e=authorizationAttemptId(t);e!==void 0&&(this.entries.some(t=>t.kind===`authorization`&&t.attemptId===e)||this.entries.push({attemptId:e,kind:`authorization`,payload:t,sequence:this.nextSequence++}))}}takeAuthorizations(e){let t=this.entries.filter(t=>t.kind===`authorization`&&e.has(t.attemptId));if(!(t.length===0||new Set(t.map(e=>e.attemptId)).size<e.size))return this.retain(e=>!t.includes(e)),t.map(e=>e.payload)}delivery(e){return this.entries.find(t=>t.kind===`delivery`&&t.sequence===e)?.delivery}replaceDelivery(e,t){let n=this.entries.findIndex(t=>t.kind===`delivery`&&t.sequence===e);if(!(n<0)){if(t===void 0){this.entries.splice(n,1);return}this.entries[n]={delivery:t,kind:`delivery`,sequence:e}}}takeSteering(e,t,n){let r=this.entries.filter(r=>r.kind===`delivery`&&e.has(r.sequence)&&isSteeringDelivery(r.delivery,t,{heldOnPerson:n?.heldSince!==void 0&&r.sequence>=n.heldSince}));if(r.length!==0)return this.retain(e=>e.kind!==`delivery`||!r.includes(e)),{delivery:combine(r),handoffEligible:!1,kind:`turn`,sequences:r.map(({sequence:e})=>e)}}takeNext(e){this.retain(e=>e.kind!==`authorization`);let t=this.entries.shift();if(t===void 0)return;if(t.kind===`control`)return{control:t.control,kind:`control`};let n=[t,...this.takeFollowingDeliveriesFrom(t)],r=n.map(({sequence:e})=>e),i=combine(n);return{delivery:i,handoffEligible:r.length===1&&r[0]===e?.freshSequence&&i.caller===void 0&&this.entries.length===0,kind:`turn`,sequences:r}}takeFollowingDeliveriesFrom(e){let t=principalOf(e.delivery.auth),n=[],r=e.delivery.caller?.callId;for(;;){let e=this.entries[0];if(e?.kind!==`delivery`||t===ANONYMOUS_PRINCIPAL||principalOf(e.delivery.auth)!==t||r!==void 0&&e.delivery.caller!==void 0&&e.delivery.caller.callId!==r)break;n.push(e),this.entries.shift(),r??=e.delivery.caller?.callId}return n}retain(e){let t=this.entries.filter(e);this.entries.splice(0,this.entries.length,...t)}};function isSteeringDelivery(e,t,n){return(n?.heldOnPerson===!0||(e.turnPolicy??`steer`)===`steer`)&&(e.caller===void 0||e.caller.callId===t.callerCallId)&&(e.auth===void 0||principalOf(e.auth)===t.principal)}function isSteeringMessage(e,t){return isSteeringDelivery(e,t)&&e.payloads.some(e=>e.message!==void 0&&e.inputResponses===void 0)}function combine(e){return e.length===1?e[0].delivery:coalesceDeliveries(e.map(({delivery:e})=>e))}function authorizationAttemptId(e){let t=e.authorizationCallback;return typeof t?.attemptId==`string`?t.attemptId:void 0}export{SessionInputQueue,isSteeringDelivery,isSteeringMessage};
|
|
1
|
+
import{DELIVERY_IDEMPOTENCY_WINDOW}from"#channel/delivery-idempotency.js";import{coalesceDeliveries}from"#harness/messages.js";import{ANONYMOUS_PRINCIPAL,principalOf}from"#execution/session/principal.js";var SessionInputQueue=class{entries=[];admittedKeys;nextSequence=0;constructor(e){this.admittedKeys=new Set(e)}get admittedDeliveryKeys(){return[...this.admittedKeys]}isDuplicate(e){return e.idempotencyKey!==void 0&&this.admittedKeys.has(e.idempotencyKey)}get pendingCount(){return this.entries.length}get nextAdmission(){return this.nextSequence}enqueueDelivery(e){if(this.isDuplicate(e))return;e.idempotencyKey!==void 0&&(this.admittedKeys.add(e.idempotencyKey),this.admittedKeys.size>DELIVERY_IDEMPOTENCY_WINDOW&&this.admittedKeys.delete(this.admittedKeys.values().next().value));let t={delivery:e,sequence:this.nextSequence++};return this.entries.push({...t,kind:`delivery`}),t}enqueueControl(e){this.entries.push({control:e,kind:`control`,sequence:this.nextSequence++})}enqueueAuthorization(e){for(let t of e){let e=authorizationAttemptId(t);e!==void 0&&(this.entries.some(t=>t.kind===`authorization`&&t.attemptId===e)||this.entries.push({attemptId:e,kind:`authorization`,payload:t,sequence:this.nextSequence++}))}}takeAuthorizations(e){let t=this.entries.filter(t=>t.kind===`authorization`&&e.has(t.attemptId));if(!(t.length===0||new Set(t.map(e=>e.attemptId)).size<e.size))return this.retain(e=>!t.includes(e)),t.map(e=>e.payload)}delivery(e){return this.entries.find(t=>t.kind===`delivery`&&t.sequence===e)?.delivery}replaceDelivery(e,t){let n=this.entries.findIndex(t=>t.kind===`delivery`&&t.sequence===e);if(!(n<0)){if(t===void 0){this.entries.splice(n,1);return}this.entries[n]={delivery:t,kind:`delivery`,sequence:e}}}takeSteering(e,t,n){let r=this.entries.filter(r=>r.kind===`delivery`&&e.has(r.sequence)&&isSteeringDelivery(r.delivery,t,{heldOnPerson:n?.heldSince!==void 0&&r.sequence>=n.heldSince}));if(r.length!==0)return this.retain(e=>e.kind!==`delivery`||!r.includes(e)),{delivery:combine(r),handoffEligible:!1,kind:`turn`,sequences:r.map(({sequence:e})=>e)}}takeNext(e){this.retain(e=>e.kind!==`authorization`);let t=this.entries.shift();if(t===void 0)return;if(t.kind===`control`)return{control:t.control,kind:`control`};let n=[t,...this.takeFollowingDeliveriesFrom(t)],r=n.map(({sequence:e})=>e),i=combine(n);return{delivery:i,handoffEligible:r.length===1&&r[0]===e?.freshSequence&&i.caller===void 0&&this.entries.length===0,kind:`turn`,sequences:r}}takeFollowingDeliveriesFrom(e){let t=principalOf(e.delivery.auth),n=[],r=e.delivery.caller?.callId;for(;;){let e=this.entries[0];if(e?.kind!==`delivery`||t===ANONYMOUS_PRINCIPAL||principalOf(e.delivery.auth)!==t||r!==void 0&&e.delivery.caller!==void 0&&e.delivery.caller.callId!==r)break;n.push(e),this.entries.shift(),r??=e.delivery.caller?.callId}return n}retain(e){let t=this.entries.filter(e);this.entries.splice(0,this.entries.length,...t)}};function isSteeringDelivery(e,t,n){return(n?.heldOnPerson===!0||(e.turnPolicy??`steer`)===`steer`)&&(e.caller===void 0||e.caller.callId===t.callerCallId)&&(e.auth===void 0||principalOf(e.auth)===t.principal)}function isSteeringMessage(e,t){return isSteeringDelivery(e,t)&&e.payloads.some(e=>e.message!==void 0&&e.inputResponses===void 0)}function combine(e){return e.length===1?e[0].delivery:coalesceDeliveries(e.map(({delivery:e})=>e))}function authorizationAttemptId(e){let t=e.authorizationCallback;return typeof t?.attemptId==`string`?t.attemptId:void 0}export{SessionInputQueue,isSteeringDelivery,isSteeringMessage};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SessionStateMap } from "#harness/types.js";
|
|
2
|
+
import type { SessionHistoryMessage } from "#shared/session-history.js";
|
|
3
|
+
export declare function withPendingHistory(state: SessionStateMap | undefined, history: readonly SessionHistoryMessage[] | undefined): SessionStateMap | undefined;
|
|
4
|
+
export declare function readPendingHistory(state: SessionStateMap | undefined): readonly SessionHistoryMessage[];
|
|
5
|
+
export declare function withoutPendingHistory(state: SessionStateMap | undefined): SessionStateMap | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const PENDING_HISTORY_STATE_KEY=`eve.session.pendingHistory`;function withPendingHistory(e,t){return t===void 0||t.length===0?e:{...e,[PENDING_HISTORY_STATE_KEY]:t}}function readPendingHistory(e){return e?.[PENDING_HISTORY_STATE_KEY]??[]}function withoutPendingHistory(e){if(e===void 0||!(PENDING_HISTORY_STATE_KEY in e))return e;let{[PENDING_HISTORY_STATE_KEY]:t,...n}=e;return n}export{readPendingHistory,withPendingHistory,withoutPendingHistory};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openSignIns}from"#protocol/session-projection.js";import{runtimeWait}from"#harness/session-machine/view.js";import{readHitlState}from"#harness/hitl/index.js";import{
|
|
1
|
+
import{openSignIns}from"#protocol/session-projection.js";import{runtimeWait}from"#harness/session-machine/view.js";import{readHitlState}from"#harness/hitl/index.js";import{ownOpenRequestIds}from"#harness/session-machine/transitions.js";import{sessionView}from"#harness/session-machine/commit.js";function derivePendingState(e,t){let{signIns:n}=readHitlState(e.state),r={authorizationAttemptIds:n.length===0?void 0:n.flatMap(e=>e.attemptId===void 0?[]:[e.attemptId]),hasPendingAuthorization:openSignIns(t).length>0,hasPendingInputBatch:ownOpenRequestIds(sessionView(t,e.state)).size>0},i=runtimeWait(e.state);return i===void 0?r:{...r,hasRunsToDispatch:i.tasks.length>0,pendingCoordinationCallIds:i.callIds,pendingTaskToolCalls:i.taskToolCalls}}export{derivePendingState};
|
|
@@ -34,6 +34,7 @@ export type SessionStart =
|
|
|
34
34
|
readonly kind: "parked";
|
|
35
35
|
};
|
|
36
36
|
export interface SessionBoot {
|
|
37
|
+
readonly admittedDeliveryKeys: readonly string[];
|
|
37
38
|
readonly anchor: SessionAnchor;
|
|
38
39
|
readonly caller: TurnCaller | undefined;
|
|
39
40
|
readonly capabilities?: SessionCapabilities;
|
|
@@ -46,7 +47,6 @@ export interface SessionBoot {
|
|
|
46
47
|
readonly sessionId: string;
|
|
47
48
|
readonly sessionState: DurableSessionState;
|
|
48
49
|
readonly sessionTimeoutControl?: SessionTimeoutControl;
|
|
49
|
-
readonly sessionTimeoutDeadline?: Date;
|
|
50
50
|
readonly sessionTimeoutMs: number | false;
|
|
51
51
|
readonly sessionWritable: WritableStream<Uint8Array>;
|
|
52
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{workingTasks}from"#execution/tasks/table.js";import{settleCancelledTurnStep}from"#execution/settle-cancelled-turn-step.js";import"#execution/session-inbox/inbox.js";import{signalSessionAnchorStep}from"#execution/session/handoff-steps.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";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,terminalEmitted:!1},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}),o={output:``,isError:!0},s;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:``}:(o=await finalizeSession(s.outcome,{caller:i.caller,cursor:r,sessionWritable:e.sessionWritable}),i.terminalEmitted=!0,o)}),o}catch(t){throw i.terminalEmitted||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,s=new SessionExecution({capabilities:e.capabilities,cursor:n,inbox:i,queue:o,sessionId:e.sessionId}),c=e.sessionTimeoutControl,nextParkedActivity=async()=>{for(;;){let e=await nextTurnDelivery({cursor:n,hasWorkingTasks:()=>workingTasks(sessionTaskTable(n)).length>0,inbox:i,queue:o});if(e.kind===`workflow`){await s.handleWorkflowMessage(e.message);continue}if(e.kind===`cancel-working-tasks`){await cancelWorkingTasks(n,`turn_cancelled`);continue}return e}},l=e.initialTurnControl??(e.anchor.kind===`self`?createTurnControl():void 0),u=0,d=!1,runTurn=async e=>{let t=a.caller,n=l;l=void 0,a.turnId=`turn_${String(u++)}`;let r=await s.runTurn(e,{caller:t,control:n});return r.caller!==void 0&&(a.caller=r.caller),r.compacted===!0&&(d=!0),r},transferState=()=>({history:n.history,serializedContext:n.serializedContext,sessionState:n.sessionState}),
|
|
1
|
+
import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{workingTasks}from"#execution/tasks/table.js";import{settleCancelledTurnStep}from"#execution/settle-cancelled-turn-step.js";import"#execution/session-inbox/inbox.js";import{signalSessionAnchorStep}from"#execution/session/handoff-steps.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";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,terminalEmitted:!1},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}),o={output:``,isError:!0},s;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:``}:(o=await finalizeSession(s.outcome,{caller:i.caller,cursor:r,sessionWritable:e.sessionWritable}),i.terminalEmitted=!0,o)}),o}catch(t){throw i.terminalEmitted||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,nextParkedActivity=async()=>{for(;;){let e=await nextTurnDelivery({cursor:n,hasWorkingTasks:()=>workingTasks(sessionTaskTable(n)).length>0,inbox:i,queue:o});if(e.kind===`workflow`){await s.handleWorkflowMessage(e.message);continue}if(e.kind===`cancel-working-tasks`){await cancelWorkingTasks(n,`turn_cancelled`);continue}if(!(e.kind===`expired`&&c!==void 0&&((o.pendingCount>0||i.hasPending())&&c.recordActivity(),await c.handleTimerElapsed()===`extended`)))return e}},l=e.initialTurnControl??(e.anchor.kind===`self`?createTurnControl():void 0),u=0,d=!1,runTurn=async e=>{let t=a.caller,n=l;l=void 0,a.turnId=`turn_${String(u++)}`;let r=await s.runTurn(e,{caller:t,control:n});return c?.recordActivity(),r.caller!==void 0&&(a.caller=r.caller),r.compacted===!0&&(d=!0),r},transferState=()=>({admittedDeliveryKeys:o.admittedDeliveryKeys,history:n.history,serializedContext:n.serializedContext,sessionState:n.sessionState}),compactionHandoffReady=()=>d&&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=>{let t=await n.advanceWithHistory(t=>settleCancelledTurnStep({...t,reportUsage:e}));return a.caller=void 0,t},awaitPrewarmedAction=async()=>{for(;;){let e=await nextParkedActivity();switch(e.kind){case`closed`:return i.takenOver?await r.adoptTakeover():{kind:`terminal`,outcome:{kind:`expired`}};case`expired`:case`reset`:return{kind:`terminal`,outcome:{kind:`expired`}};case`clear`:case`compact`:continue;case`turn`:return await runDeliveredTurn(e);case`cancel-turn`:continue}}},runInitialAction=async()=>{switch(e.start.kind){case`first-message`:return 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(l.cancelled===!0){let{caller:t}=a,n=await settleCancelledTurn(t!==void 0);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;let n=await nextParkedActivity();switch(n.kind){case`closed`:return i.takenOver?await r.adoptTakeover():{kind:`terminal`,outcome:{kind:`expired`}};case`expired`:case`reset`:return{kind:`terminal`,outcome:{kind:`expired`}};case`clear`:case`compact`:l=await runTurn({control:n.kind});continue;case`cancel-turn`:await s.cancelTurnWork(),await settleCancelledTurn(!1),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{l?.dispose(),await c?.dispose()}}export{failSession,runPreparedSession};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SessionInboxHandle } from "#execution/session-inbox/inbox.js";
|
|
2
|
+
export interface RunWatch {
|
|
3
|
+
/** Resolves once the run has ended; never settles once stopped. */
|
|
4
|
+
readonly ended: Promise<void>;
|
|
5
|
+
stop(): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Watches a counterpart run so a wait on it has a way out when that run is
|
|
9
|
+
* gone. Durable sleeps between checks keep it deterministic under replay;
|
|
10
|
+
* `stop()` ends it before its next check.
|
|
11
|
+
*/
|
|
12
|
+
export declare function watchRunEnd(runId: string): RunWatch;
|
|
13
|
+
/**
|
|
14
|
+
* Opens the inbox's handover gate with nothing restored if `sourceRunId` ends
|
|
15
|
+
* before its handover arrives: an ended run can never send it. The watch
|
|
16
|
+
* starts only once a read waits on the gate, so a handover that arrives
|
|
17
|
+
* before it is needed costs nothing.
|
|
18
|
+
*/
|
|
19
|
+
export declare function abandonHandoverIfRunEnds(inbox: SessionInboxHandle, handover: {
|
|
20
|
+
readonly attemptKey: string;
|
|
21
|
+
readonly sourceRunId: string;
|
|
22
|
+
}): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sleep}from"#compiled/@workflow/core/index.js";import{hasRunEndedStep}from"#execution/session/handoff-steps.js";function watchRunEnd(e){let t=!1;return{ended:(async()=>{for(;!t&&(await sleep(`10s`),!t);)if(await hasRunEndedStep({runId:e}).catch(()=>!1)&&!t)return;return await new Promise(()=>{})})(),stop(){t=!0}}}function abandonHandoverIfRunEnds(e,t){e.whenBlockedOnHandover().then(()=>{if(!e.awaitingHandover)return;let n=watchRunEnd(t.sourceRunId);e.whenHandoverSettled().then(()=>n.stop()),n.ended.then(()=>e.abandonHandover(t.attemptKey))})}export{abandonHandoverIfRunEnds,watchRunEnd};
|
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Workflow-body handle for one owner's idle timeout. Activity moves the
|
|
3
|
+
* deadline only in memory; when the durable timer fires before the session
|
|
4
|
+
* has been idle for the whole window, the owner re-arms it for the new
|
|
5
|
+
* deadline. An active session therefore costs one timer per window, not one
|
|
6
|
+
* per turn.
|
|
7
|
+
*/
|
|
2
8
|
export interface SessionTimeoutControl {
|
|
3
9
|
dispose(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Answers this owner's elapsed timer: `expired` once the session has been
|
|
12
|
+
* idle for the whole window, otherwise `extended` after arming a timer for
|
|
13
|
+
* the deadline that the latest activity set.
|
|
14
|
+
*/
|
|
15
|
+
handleTimerElapsed(): Promise<"expired" | "extended">;
|
|
16
|
+
/** Restarts the idle window from now. */
|
|
17
|
+
recordActivity(): void;
|
|
4
18
|
start(): Promise<void>;
|
|
5
19
|
}
|
|
6
|
-
/** Creates
|
|
20
|
+
/** Creates the idle timeout for one owner run, or `undefined` when timeouts are disabled. */
|
|
7
21
|
export declare function createSessionTimeoutControl(input: {
|
|
8
|
-
readonly deadline: Date;
|
|
9
22
|
readonly sessionId: string;
|
|
10
|
-
|
|
23
|
+
readonly timeoutMs: number | false;
|
|
24
|
+
}): SessionTimeoutControl | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sessionCommandHookToken}from"#execution/session-inbox/address.js";import{getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{cancelSessionTimeoutStep,startSessionTimeoutStep}from"#execution/session/timeout-steps.js";function createSessionTimeoutControl(e){let
|
|
1
|
+
import{sessionCommandHookToken}from"#execution/session-inbox/address.js";import{getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{cancelSessionTimeoutStep,startSessionTimeoutStep}from"#execution/session/timeout-steps.js";function createSessionTimeoutControl(e){let{sessionId:t,timeoutMs:n}=e;if(n===!1)return;let r=Date.now(),i,a,arm=async()=>{a??=(async()=>{i=await startSessionTimeoutStep({deadline:new Date(r+n),ownerRunId:getWorkflowMetadata().workflowRunId,token:sessionCommandHookToken(t)})})(),await a};return{async dispose(){try{await a}catch{}if(i===void 0)return;let e=i;i=void 0,await cancelSessionTimeoutStep({runId:e.runId})},async handleTimerElapsed(){return Date.now()>=r+n?`expired`:(i=void 0,a=void 0,await arm(),`extended`)},recordActivity(){r=Date.now()},start:arm}}export{createSessionTimeoutControl};
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
/** Default
|
|
1
|
+
/** Default time a session may sit idle before it completes. */
|
|
2
2
|
export declare const DEFAULT_SESSION_TIMEOUT_MS: number;
|
|
3
|
-
export declare function sessionTimeoutDeadline(timeoutMs: number | false, startedAtMs: number): Date | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const DEFAULT_SESSION_TIMEOUT_MS=2592e6;
|
|
1
|
+
const DEFAULT_SESSION_TIMEOUT_MS=2592e6;export{DEFAULT_SESSION_TIMEOUT_MS};
|