eve 0.71.3 → 0.72.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 +30 -0
- package/README.md +22 -6
- package/dist/src/acp/adapter.js +1 -1
- package/dist/src/ai/decide.d.ts +7 -0
- package/dist/src/ai/decide.js +1 -0
- package/dist/src/chunks/{use-eve-agent-CFCaYnrI.js → use-eve-agent-C1GYGCtb.js} +698 -388
- package/dist/src/chunks/{use-eve-agent-DcDhXNv1.js → use-eve-agent-hZJ7CB8t.js} +698 -388
- package/dist/src/cli/commands/integration-setup.js +1 -1
- package/dist/src/cli/commands/registry.js +1 -1
- package/dist/src/cli/commands/trace-detail.d.ts +1 -1
- package/dist/src/cli/commands/trace-detail.js +1 -1
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-flow.d.ts +1 -0
- package/dist/src/cli/dev/tui/setup-panel.d.ts +1 -0
- package/dist/src/cli/dev/tui/setup-panel.js +2 -1
- package/dist/src/cli/dev/tui/traces/trace-conversation.d.ts +2 -2
- package/dist/src/cli/dev/tui/traces/trace-conversation.js +2 -2
- package/dist/src/cli/dev/tui/transcript-parts.d.ts +2 -1
- package/dist/src/cli/dev/tui/transcript-parts.js +1 -1
- package/dist/src/cli/dev/tui/transcript.js +1 -1
- package/dist/src/cli/dev/tui/tui-prompter.js +1 -1
- package/dist/src/client/conversation-projection.d.ts +4 -0
- package/dist/src/client/conversation-projection.js +1 -0
- package/dist/src/client/conversation-reducer.js +1 -1
- package/dist/src/client/conversation-state.d.ts +5 -26
- package/dist/src/client/conversation-state.js +1 -1
- package/dist/src/client/index.d.ts +1 -0
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/message-action-parts.d.ts +1 -11
- package/dist/src/client/message-action-parts.js +1 -1
- package/dist/src/client/message-reducer.d.ts +3 -1
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/client/session-utils.js +1 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/tool-call-state.d.ts +23 -0
- package/dist/src/client/tool-call-state.js +1 -0
- package/dist/src/client/tool-part-state.d.ts +7 -0
- package/dist/src/client/tool-part-state.js +1 -0
- package/dist/src/compiled/.vendor-stamp.json +10 -10
- package/dist/src/compiled/@ai-sdk/anthropic/index.d.ts +1453 -1358
- package/dist/src/compiled/@ai-sdk/anthropic/index.js +1 -2
- package/dist/src/compiled/@ai-sdk/code-mode/index.d.ts +172 -163
- package/dist/src/compiled/@ai-sdk/code-mode/index.js +15 -20
- package/dist/src/compiled/@ai-sdk/google/index.d.ts +772 -733
- package/dist/src/compiled/@ai-sdk/google/index.js +6 -8
- package/dist/src/compiled/@ai-sdk/mcp/index.d.ts +887 -790
- package/dist/src/compiled/@ai-sdk/mcp/index.js +1 -1
- package/dist/src/compiled/@ai-sdk/openai/index.d.ts +1722 -1691
- package/dist/src/compiled/@ai-sdk/openai/index.js +3 -14
- package/dist/src/compiled/@ai-sdk/otel/index.d.ts +216 -159
- package/dist/src/compiled/@ai-sdk/otel/index.js +3 -3
- package/dist/src/compiled/@ai-sdk/provider/index.d.ts +7542 -7271
- package/dist/src/compiled/@ai-sdk/provider/index.js +1 -3
- package/dist/src/compiled/@ai-sdk/provider-utils/index.d.ts +1799 -1600
- package/dist/src/compiled/@eve/catalog/index.js +1 -1
- package/dist/src/compiled/_chunks/workflow/dist-DXLdlucM.js +15 -0
- package/dist/src/compiled/_chunks/workflow/experimental-decision-BrfWf6-n.js +3 -0
- package/dist/src/compiler/extension-compatibility.d.ts +36 -20
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/dynamic-tool-metadata.d.ts +1 -0
- package/dist/src/context/providers/session.js +1 -1
- package/dist/src/evals/define-eval.d.ts +1 -1
- package/dist/src/evals/judge.d.ts +1 -1
- package/dist/src/evals/judge.js +2 -2
- package/dist/src/evals/types.d.ts +8 -8
- package/dist/src/execution/cancel-descendant-turns-step.d.ts +1 -0
- package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
- package/dist/src/execution/cancelled-model-call-batch.js +1 -1
- package/dist/src/execution/coordination-dispatch-shared.js +1 -1
- package/dist/src/execution/coordination-dispatch-step.js +1 -1
- package/dist/src/execution/durable-session-read.d.ts +5 -0
- package/dist/src/execution/durable-session-read.js +1 -0
- package/dist/src/execution/durable-session-store.d.ts +4 -10
- package/dist/src/execution/durable-session-store.js +1 -1
- package/dist/src/execution/dynamic-connections.d.ts +3 -3
- package/dist/src/execution/dynamic-connections.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/legacy-session/interrupt-step.js +1 -1
- package/dist/src/execution/legacy-session/snapshot.d.ts +3 -0
- package/dist/src/execution/legacy-session/snapshot.js +1 -1
- package/dist/src/execution/model-call-batching.js +1 -1
- package/dist/src/execution/node-step.d.ts +2 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/publish-session-events.d.ts +7 -2
- package/dist/src/execution/publish-session-events.js +1 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/answer-caller.js +1 -1
- package/dist/src/execution/session/checkpoint-migrations.js +1 -1
- package/dist/src/execution/session/finalization.js +1 -1
- package/dist/src/execution/session/handoff-steps.d.ts +3 -1
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +1 -1
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/pending-turn-state.d.ts +8 -3
- package/dist/src/execution/session/pending-turn-state.js +1 -1
- package/dist/src/execution/session/task-tool-tracing-step.d.ts +5 -0
- package/dist/src/execution/session/task-tool-tracing-step.js +1 -0
- 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.d.ts +1 -0
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/settle-cancelled-turn-step.d.ts +4 -6
- package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
- package/dist/src/execution/tasks/start.d.ts +3 -3
- package/dist/src/execution/tasks/start.js +1 -1
- package/dist/src/execution/tasks/steps.d.ts +1 -1
- package/dist/src/execution/tasks/steps.js +1 -1
- package/dist/src/execution/terminal-session-completion-step.d.ts +5 -1
- package/dist/src/execution/terminal-session-completion-step.js +1 -1
- package/dist/src/execution/terminal-session-failure-step.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/connection-tools.js +1 -1
- package/dist/src/execution/tools/workflow/harness-definition.js +1 -1
- package/dist/src/execution/tools/workflow/step.js +1 -1
- package/dist/src/execution/tools/workflow/withdraw-step.d.ts +7 -9
- package/dist/src/execution/tools/workflow/withdraw-step.js +1 -1
- package/dist/src/execution/workflow-trace-context.d.ts +2 -2
- package/dist/src/harness/authorization.d.ts +4 -2
- package/dist/src/harness/authorization.js +1 -1
- package/dist/src/harness/{compaction.js → compaction/engine.js} +1 -1
- package/dist/src/harness/compaction/step.d.ts +46 -0
- package/dist/src/harness/compaction/step.js +1 -0
- package/dist/src/harness/coordination.d.ts +32 -68
- package/dist/src/harness/coordination.js +1 -1
- package/dist/src/harness/current-messages.d.ts +1 -3
- package/dist/src/harness/current-messages.js +1 -1
- package/dist/src/harness/emission.d.ts +4 -52
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/execute-tool.d.ts +1 -0
- package/dist/src/harness/final-output.d.ts +5 -0
- package/dist/src/harness/final-output.js +1 -1
- package/dist/src/harness/hitl/approvals.d.ts +115 -0
- package/dist/src/harness/hitl/approvals.js +1 -0
- package/dist/src/harness/hitl/approved-call-callers.d.ts +14 -0
- package/dist/src/harness/hitl/approved-call-callers.js +1 -0
- package/dist/src/harness/hitl/approved-calls.d.ts +37 -0
- package/dist/src/harness/hitl/approved-calls.js +1 -0
- package/dist/src/harness/hitl/budget.d.ts +21 -0
- package/dist/src/harness/hitl/budget.js +1 -0
- package/dist/src/harness/{approval-candidates.d.ts → hitl/candidates.d.ts} +9 -18
- package/dist/src/harness/hitl/candidates.js +1 -0
- package/dist/src/harness/hitl/coordinator.js +1 -0
- package/dist/src/harness/hitl/delivery.d.ts +37 -0
- package/dist/src/harness/hitl/delivery.js +1 -0
- package/dist/src/harness/hitl/index.d.ts +49 -0
- package/dist/src/harness/hitl/index.js +1 -0
- package/dist/src/harness/hitl/intake.d.ts +67 -0
- package/dist/src/harness/hitl/intake.js +1 -0
- package/dist/src/harness/{stale-input-responses.d.ts → hitl/stale-responses.d.ts} +5 -3
- package/dist/src/harness/hitl/stale-responses.js +3 -0
- package/dist/src/harness/inline-tool-authorization.d.ts +4 -0
- package/dist/src/harness/inline-tool-authorization.js +1 -1
- package/dist/src/harness/input-extraction.d.ts +1 -10
- package/dist/src/harness/input-extraction.js +1 -1
- package/dist/src/harness/input-request-resolution.d.ts +1 -5
- package/dist/src/harness/input-request-resolution.js +1 -1
- package/dist/src/harness/model-call/call.d.ts +78 -0
- package/dist/src/harness/model-call/call.js +1 -0
- package/dist/src/harness/{model-call-error.d.ts → model-call/errors.d.ts} +1 -1
- package/dist/src/harness/model-call/failure.d.ts +52 -0
- package/dist/src/harness/model-call/failure.js +1 -0
- package/dist/src/harness/model-call/model.d.ts +18 -0
- package/dist/src/harness/model-call/model.js +1 -0
- package/dist/src/harness/model-call/recovery.d.ts +52 -0
- package/dist/src/harness/model-call/recovery.js +1 -0
- package/dist/src/harness/model-call/request.d.ts +30 -0
- package/dist/src/harness/model-call/request.js +3 -0
- package/dist/src/harness/model-call/response.d.ts +39 -0
- package/dist/src/harness/model-call/response.js +1 -0
- package/dist/src/harness/model-call/retry.d.ts +11 -0
- package/dist/src/harness/model-call/retry.js +1 -0
- package/dist/src/harness/model-call/run.d.ts +38 -0
- package/dist/src/harness/model-call/run.js +1 -0
- package/dist/src/harness/model-call/tools.d.ts +48 -0
- package/dist/src/harness/model-call/tools.js +1 -0
- package/dist/src/harness/model-call/usage.d.ts +23 -0
- package/dist/src/harness/model-call/usage.js +1 -0
- package/dist/src/harness/nested-actions.d.ts +2 -2
- package/dist/src/harness/provider-tools.d.ts +2 -2
- package/dist/src/harness/provider-tools.js +1 -1
- package/dist/src/harness/proxy-input-requests.d.ts +4 -12
- package/dist/src/harness/proxy-input-requests.js +1 -1
- package/dist/src/harness/session-machine/commit.d.ts +28 -0
- package/dist/src/harness/session-machine/commit.js +1 -0
- package/dist/src/harness/session-machine/current.d.ts +29 -0
- package/dist/src/harness/session-machine/current.js +1 -0
- package/dist/src/harness/session-machine/events.d.ts +6 -0
- package/dist/src/harness/session-machine/events.js +1 -0
- package/dist/src/harness/session-machine/resolver-events.d.ts +12 -0
- package/dist/src/harness/session-machine/resolver-events.js +1 -0
- package/dist/src/harness/session-machine/state.d.ts +47 -0
- package/dist/src/harness/session-machine/state.js +1 -0
- package/dist/src/harness/session-machine/transitions.d.ts +188 -0
- package/dist/src/harness/session-machine/transitions.js +1 -0
- package/dist/src/harness/session-machine/view.d.ts +58 -0
- package/dist/src/harness/session-machine/view.js +1 -0
- package/dist/src/harness/step/after-model.d.ts +7 -0
- package/dist/src/harness/step/after-model.js +1 -0
- package/dist/src/harness/step/context.d.ts +59 -0
- package/dist/src/harness/step/context.js +1 -0
- package/dist/src/harness/step/intake.d.ts +34 -0
- package/dist/src/harness/step/intake.js +1 -0
- package/dist/src/harness/step/prompt.d.ts +37 -0
- package/dist/src/harness/step/prompt.js +1 -0
- package/dist/src/harness/step-hooks.d.ts +8 -13
- package/dist/src/harness/step-hooks.js +1 -1
- package/dist/src/harness/tool-loop.d.ts +7 -22
- package/dist/src/harness/tool-loop.js +1 -3
- package/dist/src/harness/tools.d.ts +13 -0
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/harness/turn-tag-state.d.ts +1 -1
- package/dist/src/harness/types.d.ts +6 -0
- package/dist/src/instrumentation/ai-sdk-hook-bridge.d.ts +1 -1
- package/dist/src/instrumentation/ai-sdk-hook-bridge.js +1 -1
- package/dist/src/instrumentation/content.js +1 -1
- package/dist/src/instrumentation/dispatch.js +1 -1
- package/dist/src/instrumentation/lifecycle.d.ts +28 -56
- package/dist/src/instrumentation/native-events.d.ts +2 -1
- package/dist/src/instrumentation/native-events.js +1 -1
- package/dist/src/instrumentation/provider.d.ts +1 -1
- package/dist/src/instrumentation/runtime-context.d.ts +2 -3
- package/dist/src/instrumentation/runtime-context.js +1 -1
- package/dist/src/instrumentation/runtime.d.ts +11 -1
- package/dist/src/instrumentation/runtime.js +1 -1
- package/dist/src/instrumentation/state.d.ts +6 -1
- package/dist/src/instrumentation/state.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/attachments/limited-read.d.ts +16 -0
- package/dist/src/internal/attachments/limited-read.js +1 -0
- package/dist/src/internal/authored-definition/schema-backed.d.ts +2 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/mcp/published-tools.d.ts +13 -0
- package/dist/src/internal/mcp/published-tools.js +1 -0
- package/dist/src/internal/mcp/request-trace-context.d.ts +12 -0
- package/dist/src/internal/mcp/request-trace-context.js +1 -0
- package/dist/src/internal/mcp/streamable-http-server.d.ts +7 -3
- package/dist/src/internal/mcp/streamable-http-server.js +1 -1
- package/dist/src/internal/model-auth/transport.d.ts +3 -3
- package/dist/src/internal/model-auth/transport.js +1 -1
- package/dist/src/models/auto.d.ts +5 -5
- package/dist/src/models/auto.js +2 -2
- package/dist/src/protocol/message.d.ts +7 -0
- package/dist/src/protocol/message.js +1 -1
- package/dist/src/protocol/session-projection.d.ts +159 -0
- package/dist/src/protocol/session-projection.js +1 -0
- package/dist/src/public/ai/index.d.ts +1 -1
- package/dist/src/public/ai/index.js +1 -1
- package/dist/src/public/channels/chat-sdk/attachment-refs.d.ts +15 -0
- package/dist/src/public/channels/chat-sdk/attachment-refs.js +1 -0
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +11 -5
- package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -1
- package/dist/src/public/channels/discord/attachments.d.ts +15 -0
- package/dist/src/public/channels/discord/attachments.js +1 -0
- package/dist/src/public/channels/discord/discordChannel.js +1 -1
- package/dist/src/public/channels/discord/inbound.d.ts +13 -0
- package/dist/src/public/channels/discord/inbound.js +1 -1
- package/dist/src/public/channels/linear/inbound-uploads.d.ts +21 -0
- package/dist/src/public/channels/linear/inbound-uploads.js +1 -0
- package/dist/src/public/channels/linear/linearChannel.js +1 -1
- package/dist/src/public/channels/linq/inboundContent.d.ts +7 -1
- package/dist/src/public/channels/linq/inboundContent.js +1 -1
- package/dist/src/public/channels/linq/linqChannel.js +1 -1
- package/dist/src/public/channels/mcp.d.ts +17 -2
- package/dist/src/public/channels/mcp.js +1 -1
- package/dist/src/public/channels/photon/attachments.d.ts +21 -0
- package/dist/src/public/channels/photon/attachments.js +1 -0
- package/dist/src/public/channels/photon/photonIMessageChannel.js +1 -1
- package/dist/src/public/channels/slack/attachments.d.ts +3 -1
- package/dist/src/public/channels/slack/attachments.js +1 -1
- package/dist/src/public/channels/slack/slackChannel.js +1 -1
- package/dist/src/public/channels/teams/attachments.d.ts +4 -4
- package/dist/src/public/channels/teams/attachments.js +1 -1
- package/dist/src/public/channels/telegram/attachments.js +1 -1
- package/dist/src/public/channels/twilio/api.d.ts +7 -0
- package/dist/src/public/channels/twilio/api.js +1 -1
- package/dist/src/public/channels/twilio/inbound.d.ts +7 -0
- package/dist/src/public/channels/twilio/inbound.js +2 -2
- package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
- package/dist/src/public/definitions/connections/mcp.d.ts +1 -1
- package/dist/src/public/definitions/connections/openapi.d.ts +1 -1
- package/dist/src/react/index.d.ts +1 -0
- package/dist/src/react/index.js +1 -1
- package/dist/src/runtime/agent/mock-model-adapter.js +2 -2
- package/dist/src/runtime/resolve-tool.js +1 -1
- package/dist/src/setup/boxes/resolve-provisioning.d.ts +2 -0
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/cli/prompt-ui.d.ts +3 -0
- package/dist/src/setup/cli/prompt-ui.js +3 -1
- package/dist/src/setup/cli/select-component.d.ts +1 -0
- package/dist/src/setup/cli/select-component.js +1 -1
- package/dist/src/setup/flows/ensure-vercel-project.d.ts +2 -0
- package/dist/src/setup/flows/ensure-vercel-project.js +1 -1
- package/dist/src/setup/integrations/discord/api.js +1 -1
- package/dist/src/setup/integrations/web/auth-options.d.ts +4 -0
- package/dist/src/setup/integrations/web/auth-options.js +1 -0
- package/dist/src/setup/integrations/web/auth-scaffold.d.ts +7 -0
- package/dist/src/setup/integrations/web/auth-scaffold.js +1 -0
- package/dist/src/setup/integrations/web/provision-auth.d.ts +3 -0
- package/dist/src/setup/integrations/web/provision-auth.js +1 -0
- package/dist/src/setup/integrations/web/setup.d.ts +11 -6
- package/dist/src/setup/integrations/web/setup.js +3 -3
- package/dist/src/setup/prompter.d.ts +2 -0
- package/dist/src/setup/prompter.js +1 -1
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
- package/dist/src/setup/scaffold/create/web-template.js +1 -0
- package/dist/src/setup/scaffold/update/web-options.js +1 -1
- package/dist/src/setup/vercel-project-api.d.ts +9 -0
- package/dist/src/setup/vercel-project-api.js +1 -1
- package/dist/src/setup/vercel-project.d.ts +4 -2
- package/dist/src/setup/vercel-project.js +0 -0
- package/dist/src/shared/web-search.d.ts +1 -1
- package/dist/src/subagents/adapter.js +1 -1
- package/dist/src/subagents/event-proxy-step.js +1 -1
- package/dist/src/subagents/hitl-proxy.d.ts +4 -28
- package/dist/src/subagents/hitl-proxy.js +1 -1
- package/dist/src/svelte/index.d.ts +2 -0
- package/dist/src/svelte/index.js +39 -2
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/approval/policies.d.ts +5 -5
- package/dist/src/tools/approval/policies.js +1 -1
- package/dist/src/tools/framework/agent.js +1 -1
- package/dist/src/tools/provided/agent-router.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/ask-question.js +2 -2
- package/dist/src/tools/provided/bash.js +1 -1
- package/dist/src/tools/provided/framework-tool.d.ts +3 -0
- package/dist/src/tools/provided/framework-tool.js +1 -0
- package/dist/src/tools/provided/glob.js +2 -2
- package/dist/src/tools/provided/grep.js +2 -2
- package/dist/src/tools/provided/load-skill.js +1 -1
- package/dist/src/tools/provided/no-reply.js +1 -1
- package/dist/src/tools/provided/read-file.js +2 -2
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tools/provided/sleep.js +1 -1
- package/dist/src/tools/provided/task-cancel.js +1 -1
- package/dist/src/tools/provided/task-wait.js +1 -1
- package/dist/src/tools/provided/web-fetch.js +2 -2
- package/dist/src/tools/provided/web-search.js +1 -1
- package/dist/src/tools/provided/workflow.js +1 -1
- package/dist/src/tools/provided/write-file.js +2 -2
- package/dist/src/tracing/agent-approval-instrumentation.d.ts +2 -2
- package/dist/src/tracing/agent-approval-instrumentation.js +1 -1
- package/dist/src/tracing/agent-otel-provider.js +2 -2
- package/dist/src/tracing/agent-otel-usage.d.ts +1 -1
- package/dist/src/tracing/agent-otel-usage.js +1 -1
- package/dist/src/tracing/agent-span-contract.d.ts +0 -1
- package/dist/src/tracing/agent-span-contract.js +1 -1
- package/dist/src/tracing/agent-tool-instrumentation.d.ts +16 -6
- package/dist/src/tracing/agent-tool-instrumentation.js +1 -1
- package/dist/src/tracing/agent-trace-context-codec.js +1 -1
- package/dist/src/tracing/agent-trace-state.d.ts +7 -3
- package/dist/src/tracing/invoke-tool-span.js +1 -1
- package/dist/src/tracing/local-trace-analysis.js +1 -1
- package/dist/src/vue/index.d.ts +2 -0
- package/dist/src/vue/index.js +39 -2
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +2 -2
- package/docs/channels/chat-sdk.mdx +3 -1
- package/docs/channels/custom.mdx +2 -0
- package/docs/channels/discord.mdx +5 -4
- package/docs/channels/eve.mdx +65 -0
- package/docs/channels/linear.mdx +1 -1
- package/docs/channels/linq.mdx +2 -0
- package/docs/channels/mcp.mdx +39 -1
- package/docs/channels/photon.mdx +5 -0
- package/docs/channels/teams.mdx +4 -7
- package/docs/channels/twilio.mdx +1 -1
- package/docs/concepts/built-in-tools.md +12 -0
- package/docs/concepts/sessions-runs-and-streaming.md +3 -3
- package/docs/connections/overview.mdx +1 -1
- package/docs/dynamic-configuration/meta.json +1 -1
- package/docs/evals/judge.mdx +16 -16
- package/docs/evals/overview.mdx +1 -1
- package/docs/guides/{evaluate.md → decide.md} +35 -35
- package/docs/guides/dynamic-capabilities.md +1 -1
- package/docs/guides/frontend/overview.mdx +3 -1
- package/docs/guides/hooks.md +1 -1
- package/docs/guides/instrumentation/instrumentation.mdx +23 -22
- package/docs/guides/instrumentation/otel.mdx +13 -2
- package/docs/reference/cli.md +3 -3
- package/docs/reference/typescript-api.md +4 -2
- package/docs/tools/human-in-the-loop.md +6 -4
- package/docs/tools/workflows.mdx +4 -4
- package/package.json +11 -11
- package/dist/src/ai/evaluate.d.ts +0 -7
- package/dist/src/ai/evaluate.js +0 -1
- package/dist/src/client/message-task-parts.d.ts +0 -8
- package/dist/src/client/message-task-parts.js +0 -1
- package/dist/src/compiled/_chunks/workflow/dist-C3ZE62yI.js +0 -25
- package/dist/src/compiled/_chunks/workflow/experimental-evaluation-Dm32egEG.js +0 -5
- package/dist/src/harness/active-turn-id.d.ts +0 -11
- package/dist/src/harness/active-turn-id.js +0 -1
- package/dist/src/harness/approval-candidates.js +0 -1
- package/dist/src/harness/approval-delivery-coordinator.js +0 -1
- package/dist/src/harness/approved-call-callers.d.ts +0 -11
- package/dist/src/harness/approved-call-callers.js +0 -1
- package/dist/src/harness/cancelled-turn-emission.d.ts +0 -12
- package/dist/src/harness/cancelled-turn-emission.js +0 -1
- package/dist/src/harness/emission-state.d.ts +0 -36
- package/dist/src/harness/emission-state.js +0 -1
- package/dist/src/harness/held-requests.d.ts +0 -18
- package/dist/src/harness/held-requests.js +0 -1
- package/dist/src/harness/hitl/approval-input-requests.d.ts +0 -27
- package/dist/src/harness/hitl/approval-input-requests.js +0 -1
- package/dist/src/harness/hitl/pending-input-resolution.d.ts +0 -54
- package/dist/src/harness/hitl/pending-input-resolution.js +0 -1
- package/dist/src/harness/hitl/session-limit-input-requests.d.ts +0 -12
- package/dist/src/harness/hitl/session-limit-input-requests.js +0 -1
- package/dist/src/harness/input-requests.d.ts +0 -37
- package/dist/src/harness/input-requests.js +0 -1
- package/dist/src/harness/pending-input-batches.d.ts +0 -81
- package/dist/src/harness/pending-input-batches.js +0 -1
- package/dist/src/harness/session-limit-enforcement.d.ts +0 -45
- package/dist/src/harness/session-limit-enforcement.js +0 -1
- package/dist/src/harness/stale-input-responses.js +0 -3
- package/dist/src/harness/workflow-dispatch.d.ts +0 -30
- package/dist/src/harness/workflow-dispatch.js +0 -1
- package/dist/src/public/channels/linear/inbound-images.d.ts +0 -19
- package/dist/src/public/channels/linear/inbound-images.js +0 -1
- package/dist/src/tracing/agent-action-instrumentation.d.ts +0 -26
- package/dist/src/tracing/agent-action-instrumentation.js +0 -1
- /package/dist/src/harness/{compaction.d.ts → compaction/engine.d.ts} +0 -0
- /package/dist/src/harness/{compaction-prompt.d.ts → compaction/prompt.d.ts} +0 -0
- /package/dist/src/harness/{compaction-prompt.js → compaction/prompt.js} +0 -0
- /package/dist/src/harness/{session-limit-continuation.d.ts → hitl/budget-request.d.ts} +0 -0
- /package/dist/src/harness/{session-limit-continuation.js → hitl/budget-request.js} +0 -0
- /package/dist/src/harness/{approval-delivery-coordinator.d.ts → hitl/coordinator.d.ts} +0 -0
- /package/dist/src/harness/{model-call-error.js → model-call/errors.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createActionInputAppendedEvent,createActionPartialEvent,createActionResultEvent,createActionsRequestedEvent,createMessageAppendedEvent,createMessageCompletedEvent,
|
|
1
|
+
import{createActionInputAppendedEvent,createActionPartialEvent,createActionResultEvent,createActionsRequestedEvent,createMessageAppendedEvent,createMessageCompletedEvent,createReasoningAppendedEvent,createReasoningCompletedEvent}from"#protocol/message.js";import{createRuntimeToolResultFromStepResult,createRuntimeToolResultFromToolError,createToolResultMessagePartFromToolError}from"#harness/action-result-helpers.js";import{emitNestedToolActions}from"#harness/nested-actions.js";import{createInvalidToolCallInputError,isInvalidToolCall,resolveProviderToolCallRequest}from"#harness/tool-call-input-errors.js";import{collectActionPresentation,createPresentedRuntimeActionRequestFromToolCall}from"#harness/action-presentation.js";import{projectDeltaPresentation,projectResultPresentation}from"#harness/tool-presentation.js";import{createProviderStreamActionBatch}from"#harness/stream-actions.js";import{normalizeModelStreamError}from"#harness/model-call/errors.js";import{createOrderedStreamEmitter}from"#harness/ordered-stream-emitter.js";import{interruptStreamOnFailure}from"#harness/interruptible-stream.js";import{isInlineAuthorizationToolResult}from"#harness/inline-tool-authorization.js";import{normalizeAssistantStepFinishReason}from"#harness/finish-reason.js";async function emitStreamContent(e,t,n,r){let i=createOrderedStreamEmitter(e),a=createProviderStreamActionBatch({emitFn:i.emit,state:t});try{return await consumeStreamContent(i.emit,t,interruptStreamOnFailure(n,i.failureSignal),a,r)}finally{try{await a.cancel()}finally{await i.closeAndDrain()}}}function reportedFinishReason(e,t){return t&&e===`stop`?`tool-calls`:e}async function consumeStreamContent(e,t,n,r,i){let a=``,o=``,s=`stop`,c,l=new Set,u=new Set,d=new Set,f=new Set,p=new Set,m=new Set,h=[],g=[],_=new Map,v=new Map,flushCurrentMessage=async()=>{o.length!==0&&(await e(createMessageCompletedEvent({finishReason:`tool-calls`,message:o,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),o=``)},emitActionInput=async(n,r,i)=>e(createActionInputAppendedEvent({callId:n,inputTextDelta:i,sequence:t.sequence,stepIndex:t.stepIndex,toolName:r,turnId:t.turnId})),emitActionRequest=async n=>{let{action:r}=n;u.has(r.callId)||(o.trim().length>0&&await flushCurrentMessage(),u.add(r.callId),_.set(r.callId,r.input),await e(createActionsRequestedEvent({actions:[r],presentation:collectActionPresentation([n]),sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})))},collectProviderToolCall=async e=>{if(f.has(e.toolCallId)||(f.add(e.toolCallId),u.has(e.toolCallId)))return;u.add(e.toolCallId),o.trim().length>0&&await flushCurrentMessage();let t=resolveProviderToolCallRequest(e,i?.tools??new Map);if(t.toolError!==void 0){m.add(e.toolCallId),await emitActionResult(createRuntimeToolResultFromToolError(t.toolError)),p.add(e.toolCallId),g.push(createToolResultMessagePartFromToolError(t.toolError));return}_.set(t.request.action.callId,t.request.action.input),r.observe(t.request)},emitActionResult=async n=>{if(d.has(n.callId))return;d.add(n.callId),await emitNestedToolActions(e,t,n.callId);let r=n.isError===!0?void 0:projectResultPresentation(i?.tools.get(n.toolName),n.callId,_.get(n.callId),n.output);await e(createActionResultEvent({presentation:r,result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId}))},emitActionPartial=async n=>{let r=projectDeltaPresentation(i?.tools.get(n.toolName),n.callId,_.get(n.callId),n.output);await e(createActionPartialEvent({presentation:r,result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId}))},emitToolCall=async e=>{if(isInvalidToolCall(e)){m.add(e.toolCallId);return}if(!(i===void 0||i.excludedActionToolNames.has(e.toolName)))try{await emitActionRequest(createPresentedRuntimeActionRequestFromToolCall({toolCall:e,tools:i.tools}))}catch(t){if(t instanceof TypeError){let n=createInvalidToolCallInputError({error:t,toolCall:e});m.add(e.toolCallId),o.trim().length>0&&await flushCurrentMessage(),await emitActionResult(createRuntimeToolResultFromToolError(n)),p.add(e.toolCallId),g.push(createToolResultMessagePartFromToolError(n));return}throw t}};for await(let d of n)if(c===void 0)switch(d.type){case`reasoning-delta`:await r.flush(),a+=d.text,await e(createReasoningAppendedEvent({reasoningDelta:d.text,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId}));break;case`text-delta`:await r.flush(),a.trim().length>0&&(await e(createReasoningCompletedEvent({reasoning:a,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),a=``),o+=d.text,await e(createMessageAppendedEvent({messageDelta:d.text,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId}));break;case`tool-input-start`:if(i===void 0||d.providerExecuted===!0||i.excludedActionToolNames.has(d.toolName)){v.delete(d.id);break}await r.flush(),o.trim().length>0&&await flushCurrentMessage(),v.set(d.id,{toolName:d.toolName});break;case`tool-input-delta`:{let e=v.get(d.id);if(e===void 0)break;await r.flush(),await emitActionInput(d.id,e.toolName,d.delta);break}case`tool-input-end`:v.delete(d.id);break;case`tool-call`:{let e=d;v.delete(e.toolCallId),l.add(e.toolCallId),e.providerExecuted===!0?await collectProviderToolCall(e):(await r.flush(),await emitToolCall(e));break}case`tool-result`:{let e=d;if(e.preliminary===!0){e.providerExecuted!==!0&&await emitActionPartial(createRuntimeToolResultFromStepResult(e));break}if(e.providerExecuted===!0){await collectProviderToolCall({input:`input`in e?e.input:void 0,toolCallId:e.toolCallId,toolName:e.toolName}),await r.flush(),await emitActionResult(createRuntimeToolResultFromStepResult(e));break}if(l.has(d.toolCallId)){if(isInlineAuthorizationToolResult(e))break;u.has(d.toolCallId)&&(await emitActionResult(createRuntimeToolResultFromStepResult(e)),p.add(d.toolCallId));break}if(await r.flush(),await flushCurrentMessage(),isInlineAuthorizationToolResult(e)){p.add(d.toolCallId),h.push(e);break}await emitActionResult(createRuntimeToolResultFromStepResult(e)),p.add(d.toolCallId);break}case`tool-error`:{let e=d;e.providerExecuted===!0?(await collectProviderToolCall(e),await r.flush(),await emitActionResult(createRuntimeToolResultFromToolError(e))):u.has(e.toolCallId)&&(await emitActionResult(createRuntimeToolResultFromToolError(e)),p.add(e.toolCallId),g.push(createToolResultMessagePartFromToolError(e)));break}case`finish-step`:s=normalizeAssistantStepFinishReason(d.finishReason),await r.flush();break;case`error`:c=normalizeModelStreamError(d.error);break;case`abort`:throw new DOMException(d.reason??`The model stream was aborted.`,`AbortError`)}if(await r.flush(),c!==void 0)throw c;return a.trim().length>0&&await e(createReasoningCompletedEvent({reasoning:a,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),s!==`content-filter`&&o.trim().length>0&&await e(createMessageCompletedEvent({finishReason:reportedFinishReason(s,i?.hidesHeldText===!0),message:o,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),{emittedActionCallIds:u,handledInlineToolResultCallIds:p,invalidInputToolCallIds:m,inlineAuthorizationResults:h,trailingInlineToolResultParts:g}}export{emitStreamContent};
|
|
@@ -17,6 +17,7 @@ export interface HarnessToolDefinition {
|
|
|
17
17
|
readonly execute?: (input: any, options: ToolExecuteOptions) => any;
|
|
18
18
|
/** Optional JSON input substituted when this tool starts its workflow body. */
|
|
19
19
|
readonly executeInput?: (input: unknown) => JsonValue;
|
|
20
|
+
readonly frameworkTool?: boolean;
|
|
20
21
|
readonly frameworkAction?: "load-skill" | "task-cancel" | "task-wait";
|
|
21
22
|
readonly inputSchema: FlexibleSchema;
|
|
22
23
|
readonly name: string;
|
|
@@ -4,6 +4,11 @@ import type { JsonObject } from "#shared/json.js";
|
|
|
4
4
|
* Stable model-visible name for the kernel structured-output interception.
|
|
5
5
|
*/
|
|
6
6
|
export declare const FINAL_OUTPUT_TOOL_NAME = "final_output";
|
|
7
|
+
/**
|
|
8
|
+
* What the model reads when it gives its final output beside calls whose results it hasn't seen:
|
|
9
|
+
* the turn can't end on an answer written before them, so it answers again once they arrive.
|
|
10
|
+
*/
|
|
11
|
+
export declare const FINAL_OUTPUT_BESIDE_PENDING_CALLS = "Your final output wasn't delivered because other calls in this response were still running. Use their results, then call final_output again.";
|
|
7
12
|
/**
|
|
8
13
|
* Builds the model-facing `final_output` tool from a lowered output schema.
|
|
9
14
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineJsonSchema,toModelSchema}from"#tools/schema.js";const FINAL_OUTPUT_TOOL_NAME=`final_output
|
|
1
|
+
import{defineJsonSchema,toModelSchema}from"#tools/schema.js";const FINAL_OUTPUT_TOOL_NAME=`final_output`,FINAL_OUTPUT_BESIDE_PENDING_CALLS=`Your final output wasn't delivered because other calls in this response were still running. Use their results, then call final_output again.`;function buildFinalOutputTool(e){let t=toModelSchema(defineJsonSchema(e),`input`);return{description:`Deliver your final answer in the required structure by calling this tool. Call it exactly once, when you are done; do not answer in prose.`,inputSchema:t,outputSchema:t}}export{FINAL_OUTPUT_BESIDE_PENDING_CALLS,FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { SessionAuthContext } from "#channel/types.js";
|
|
2
|
+
import type { ModelMessage } from "ai";
|
|
3
|
+
import type { getApprovalAuditState } from "#harness/hitl/candidates.js";
|
|
4
|
+
import { type AuthorizationChallenge } from "#harness/authorization.js";
|
|
5
|
+
import { type ResolvedInputBatch } from "#harness/input-request-resolution.js";
|
|
6
|
+
import type { StepInput } from "#harness/types.js";
|
|
7
|
+
import type { RuntimeWorkflowTaskRequest } from "#shared/action-types.js";
|
|
8
|
+
import type { InputRequest } from "#shared/input.js";
|
|
9
|
+
import type { Transition } from "#harness/session-machine/commit.js";
|
|
10
|
+
import { type ResolvedStepInput } from "./delivery.js";
|
|
11
|
+
import type { StepCoordinates, SuspendedStep } from "#harness/session-machine/view.js";
|
|
12
|
+
import { type SessionView } from "#harness/session-machine/view.js";
|
|
13
|
+
/**
|
|
14
|
+
* A model response made calls that need a person's approval. The response waits in a suspended
|
|
15
|
+
* step, beside any runtime calls it made, and the turn holds until the answers arrive.
|
|
16
|
+
*/
|
|
17
|
+
export declare function parkOnApprovals(view: SessionView, input: {
|
|
18
|
+
readonly event: StepCoordinates;
|
|
19
|
+
readonly messages: readonly ModelMessage[];
|
|
20
|
+
readonly requests: readonly InputRequest[];
|
|
21
|
+
readonly tasks: readonly RuntimeWorkflowTaskRequest[];
|
|
22
|
+
readonly responseAuthRequiredRequestIds?: readonly string[];
|
|
23
|
+
readonly requester?: SuspendedStep["requester"];
|
|
24
|
+
}): Transition;
|
|
25
|
+
/** Approved workflow and agent calls join the runs their steps wait on, as their approvers. */
|
|
26
|
+
export declare function dispatch(view: SessionView, input: {
|
|
27
|
+
readonly approvers: Readonly<Record<string, SessionAuthContext>>;
|
|
28
|
+
readonly tasks: readonly RuntimeWorkflowTaskRequest[];
|
|
29
|
+
}): Transition;
|
|
30
|
+
/**
|
|
31
|
+
* Approved calls run before the delivery's own input, as the AI SDK ran them: the model reads
|
|
32
|
+
* their results first. The input waits in the queue, unreceived, for the step after.
|
|
33
|
+
*/
|
|
34
|
+
export declare function deferInput(view: SessionView, input: StepInput): Transition;
|
|
35
|
+
/** What the approval-response policies did with a delivery, before `answer` reads it. */
|
|
36
|
+
export interface ResponsePolicyPass {
|
|
37
|
+
readonly kind: "continue" | "continue-coordination" | "authorization-required" | "responses-completed" | "park";
|
|
38
|
+
readonly challenges: readonly AuthorizationChallenge[];
|
|
39
|
+
readonly feedback: readonly string[];
|
|
40
|
+
/** The delivery minus the answers the policies took, plus the settlements they reached. */
|
|
41
|
+
readonly stepInput?: StepInput;
|
|
42
|
+
readonly audit: ReturnType<typeof getApprovalAuditState>;
|
|
43
|
+
/** Responder sign-ins pending when the pass began. */
|
|
44
|
+
readonly challengesAtStart: readonly AuthorizationChallenge[];
|
|
45
|
+
}
|
|
46
|
+
/** What `answer` concluded, beyond the events and state it changed. */
|
|
47
|
+
export interface Answered extends Transition {
|
|
48
|
+
/**
|
|
49
|
+
* `continue`: the step goes on. `park`: nothing can run until more input arrives.
|
|
50
|
+
* `repeat`: a policy pass committed, so the next pass runs in a fresh step. `sign-in`: a
|
|
51
|
+
* responder must sign in first. `defer-message`: a message arrived while the session-limit
|
|
52
|
+
* prompt is open; it waits in its turn for the prompt.
|
|
53
|
+
*/
|
|
54
|
+
readonly next: "continue" | "park" | "repeat" | "sign-in" | "defer-message";
|
|
55
|
+
/** The turn's input, without the answers `answer` consumed. */
|
|
56
|
+
readonly input?: StepInput;
|
|
57
|
+
/** Whether a plain-text answer consumed the message. */
|
|
58
|
+
readonly consumedMessage?: boolean;
|
|
59
|
+
/** The batches the delivery resolved, in order. */
|
|
60
|
+
readonly resolved: readonly ResolvedInputBatch[];
|
|
61
|
+
/** A decision on the session-limit prompt. */
|
|
62
|
+
readonly limit?: {
|
|
63
|
+
readonly granted: boolean;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A delivery answers what the session asked. An approval batch resolves once every request in it
|
|
68
|
+
* has a decision: approved calls become ready to run, denied ones get their denial as a result,
|
|
69
|
+
* and `once()` approvals grant their key. A message steers the held turn instead: the first
|
|
70
|
+
* pending batch resolves with the answers it has, and the rest are ignored. A session-limit
|
|
71
|
+
* answer grants or declines a fresh budget. A partial answer waits, queued, for the rest.
|
|
72
|
+
*/
|
|
73
|
+
export declare function answer(view: SessionView, input: {
|
|
74
|
+
readonly delivery: ResolvedStepInput | undefined;
|
|
75
|
+
readonly policy: ResponsePolicyPass;
|
|
76
|
+
/** The delivery merged the queue in, so the queue empties. */
|
|
77
|
+
readonly takeQueued: boolean;
|
|
78
|
+
readonly approvalKey: (request: InputRequest) => string | undefined;
|
|
79
|
+
}): Answered;
|
|
80
|
+
/** Queued input that can run now, rather than wait for more answers. */
|
|
81
|
+
export declare function hasRunnableQueue(view: SessionView): boolean;
|
|
82
|
+
/** Keys `once()` approvals granted, except those a pending approval still asks about. */
|
|
83
|
+
export declare function grantedApprovalKeys(view: SessionView, approvalKey: (request: InputRequest) => string | undefined): ReadonlySet<string>;
|
|
84
|
+
/**
|
|
85
|
+
* The steps a delivery approves calls of, whose tools the calls run with: those it answers in
|
|
86
|
+
* full, approving at least one call, or the only pending step a plain-text answer approves.
|
|
87
|
+
*/
|
|
88
|
+
export declare function approvingSteps(view: SessionView, stepInput: StepInput | undefined): readonly SuspendedStep[];
|
|
89
|
+
/** The suspended step that holds `requestId`. */
|
|
90
|
+
export declare function stepForRequest(view: SessionView, requestId: string): SuspendedStep | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* The held turn moves on, steered or cancelled: the sign-ins it waits on end, declined, including
|
|
93
|
+
* a responder's for one of its approvals.
|
|
94
|
+
*/
|
|
95
|
+
export declare function withdrawSignIns(view: SessionView, reason: string): Transition;
|
|
96
|
+
/**
|
|
97
|
+
* The session spent its budget: it asks whether to continue instead of calling the model, and
|
|
98
|
+
* the turn ends. The prompt is the projection's open request; `answer` grants a
|
|
99
|
+
* fresh budget or declines it.
|
|
100
|
+
*/
|
|
101
|
+
export declare function requestLimit(view: SessionView, input: {
|
|
102
|
+
readonly request: InputRequest;
|
|
103
|
+
}): Transition;
|
|
104
|
+
/**
|
|
105
|
+
* Work needs a sign-in. The calls that need it stop, settling `cancelled` until it completes;
|
|
106
|
+
* an attempt it replaces fails; and each sign-in is asked for and recorded. The turn holds until
|
|
107
|
+
* every sign-in calls back. Input that waited on a responder's sign-in stays queued for it. An
|
|
108
|
+
* approved call that needs the sign-in leaves its step, so the model calls it again once the
|
|
109
|
+
* sign-in completes.
|
|
110
|
+
*/
|
|
111
|
+
export declare function requireSignIn(view: SessionView, input: {
|
|
112
|
+
readonly challenges: readonly AuthorizationChallenge[];
|
|
113
|
+
readonly callIdsByName?: ReadonlyMap<string, readonly string[]>;
|
|
114
|
+
readonly queued?: StepInput;
|
|
115
|
+
}): Transition;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{canonicalize,compactInput,hasInput,isEmptyInput,resolveTextInput,withoutResponses,withoutTurnInput}from"./delivery.js";import{openInputs,turnCoordinates}from"#protocol/session-projection.js";import{readClientContext}from"#internal/client-context.js";import{createActionResultEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageCompletedEvent}from"#protocol/message.js";import{coalesceTurnInputs,createFrameworkUserMessage}from"#harness/messages.js";import{turnPosition}from"#harness/session-machine/view.js";import{renderPendingApprovalsSnippet}from"#harness/hitl/approval-prompt.js";import{finishTurn,hold,ownOpenRequestIds,settle,stepCallIds,suspend,withResult,withoutApproved}from"#harness/session-machine/transitions.js";import{supersededChallenges,withSignIns}from"#harness/authorization.js";import{withoutCalls}from"#harness/inline-tool-authorization.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{authorizationEventFields}from"#harness/authorization-event-fields.js";import{TOOL_EXECUTION_DENIED_MESSAGE,resolveApprovalOutcome,resolveInputOutcome}from"#harness/input-request-resolution.js";import{resolveSessionLimitContinuation}from"#harness/hitl/budget-request.js";import{signInWithdrawn}from"#harness/session-machine/events.js";function parkOnApprovals(e,t){let n=t.requester?.principalType===`anonymous`?null:t.requester,r=t.messages.findIndex(e=>e.role!==`tool`),i=r===-1?t.messages:t.messages.slice(0,r),a=renderPendingApprovalsSnippet(t.requests),o=suspend(e.turn,{event:t.event,messages:t.messages.slice(i.length),requester:n,requests:t.requests,responseAuthRequiredRequestIds:t.responseAuthRequiredRequestIds,tasks:t.tasks});return{commit:[...i,...a===void 0?[]:[createFrameworkUserMessage(`context.state`,a)]],events:[createInputRequestedEvent({requests:t.requests,...t.event})],turn:o}}function dispatch(e,t){let n=e.turn.suspended.map(e=>{let n=stepCallIds(e),r=t.tasks.filter(e=>n.has(e.callId));if(r.length===0)return e;let i=withoutApproved(e,new Set(r.map(e=>e.callId))),a={...e.approvers};for(let{callId:e}of r){let n=t.approvers[e];n!==void 0&&(a[e]=n)}return{...i,tasks:[...e.tasks,...r],...Object.keys(a).length>0&&{approvers:a}}});return{events:[],turn:{...e.turn,suspended:n}}}function deferInput(e,t){return{events:[],turn:withQueued(e.turn,t)}}function withQueued(e,t){return t===void 0||isEmptyInput(t)?e:{...e,queued:e.queued===void 0?t:coalesceTurnInputs(e.queued,t)}}function answer(e,t){let{policy:n}=t,{projection:r}=e,i=turnPosition(r),a=[...n.feedback.map(e=>createMessageCompletedEvent({message:e,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId})),...reportApprovalProgress(r,n.audit,n.challengesAtStart)],o=t.takeQueued?{...e.turn,queued:void 0}:e.turn,done=e=>({events:a,resolved:[],turn:o,...e}),queue=e=>{o=withQueued(o,e)};if(n.kind===`park`)return done({next:`park`});if(n.kind===`continue-coordination`)return queue(n.stepInput),done({next:`repeat`});if(n.challenges.length>0)return done({next:`sign-in`});let s=t.delivery,c=openInputs(r).find(t=>t.request.kind===`session-limit`&&ownOpenRequestIds(e).has(t.request.requestId)),l=o.suspended.filter(e=>e.requests.length>0);if(c===void 0&&l.length===0)return done({input:s,next:`continue`});let u=c===void 0?l.length===1?l[0]:void 0:{requests:[c.request]},d=u===void 0?s:resolveTextInput(u,s),f=canonicalize(d?.inputResponses??[]),p=new Map(f.map(e=>[e.requestId,e])),m=l.filter(e=>e.requests.every(e=>p.has(e.requestId))),leftoverFor=e=>f.filter(t=>e.some(e=>e.requests.some(e=>e.requestId===t.requestId))),park=()=>(queue(compactInput(d)),done({next:`park`}));if(f.length===0&&d?.message===void 0)return park();if(c!==void 0){let e=p.get(c.request.requestId);if(e===void 0)return hasInput(s)?(queue(withoutTurnInput(d)),done({input:d,next:`defer-message`})):(queue(compactInput(d)),done({next:`park`}));let t={event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},inputs:[{outcome:resolveInputOutcome(c.request.kind,e),request:c.request,response:e}]};a.push(resolvedEvent(t));let n=leftoverFor(l);return n.length>0&&queue({inputResponses:n}),done({consumedMessage:d?.messageConsumed,input:withoutResponses(d),limit:resolveSessionLimitContinuation({requests:[c.request],responses:f}),next:`continue`,resolved:[t]})}if(m.length===0&&d?.message===void 0)return park();m.length===0&&m.push(l[0]);let h=leftoverFor(l.filter(e=>!m.includes(e)));h.length>0&&queue({inputResponses:h});let g=new Set(o.grants),_=[],v=[],y=o.suspended.map(e=>{if(!m.includes(e))return e;let n=e.messages,r=[];for(let i of e.requests){let{approved:a,reason:o,status:s}=resolveApprovalOutcome(p.get(i.requestId));if(a){g.add(t.approvalKey(i)??i.action.toolName),r.push(i);continue}n=withResult(n,{output:{reason:o,type:`execution-denied`},toolCallId:i.action.callId,toolName:i.action.toolName,type:`tool-result`}),v.push(createActionResultEvent({rejected:!0,result:{callId:i.action.callId,isError:!0,kind:`tool-result`,output:{approval:{requestId:i.requestId,status:s},code:`TOOL_EXECUTION_DENIED`,message:o??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:i.action.toolName},...e.event}))}_.push({event:e.event,inputs:e.requests.map(e=>{let t=p.get(e.requestId);return{outcome:resolveInputOutcome(e.kind,t),request:e,response:t}})});let i=[...e.approved??[],...r];return{...e,messages:n,requests:[],...i.length>0&&{approved:i}}});return a.push(..._.map(resolvedEvent),...v),o={...o,grants:[...g],suspended:y},done({consumedMessage:d?.messageConsumed,input:withoutResponses(d),next:`continue`,resolved:_})}function resolvedEvent(e){return createInputResolvedEvent({resolutions:e.inputs.map(e=>{let t={kind:e.request.kind,outcome:e.outcome,requestId:e.request.requestId};return e.response===void 0?t:{...t,response:e.response}}),...e.event})}function reportApprovalProgress(e,t,n){let r=turnCoordinates(e),isOpen=t=>{let n=e.inputs[t];return n!==void 0&&n.status!==`settled`},i=[];for(let a of n){let n=t.candidateHistory.some(e=>e.candidateId===a.candidateId&&e.status===`timed-out`),o=e.authorizations[a.attemptId??a.name];n&&o?.status===`required`&&i.push(createAuthorizationCompletedEvent({...authorizationEventFields(a),outcome:`failed`,reason:`The approval response expired. Please submit a new response.`,...r}))}for(let n of t.activeCandidates)e.candidates[n.candidateId]===void 0&&isOpen(n.requestId)&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:`pending`,requestId:n.requestId,responderPrincipalId:n.responder.principalId,...r}));for(let n of t.candidateHistory)n.status!==`allowed`&&n.status!==`authorization-required`&&e.inputs[n.requestId]!==void 0&&e.candidates[n.candidateId]?.outcome!==n.status&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:n.status,requestId:n.requestId,responderPrincipalId:n.responder.principalId,reason:n.reason,...r}));for(let e of t.settlements)isOpen(e.requestId)&&i.push(createApprovalSettledEvent({outcome:e.outcome===`allowed`?`approved`:`cancelled`,requestId:e.requestId,responderPrincipalId:e.actor.principalId,...r}));return i}function hasRunnableQueue(e){let t=e.turn.queued;if(t===void 0)return!1;if(t.message!==void 0||(t.context?.length??0)>0||readClientContext(t)!==void 0||t.outputSchema!==void 0||(t.runtimeActionResults?.length??0)>0)return!0;let n=[...t.inputResponses??[],...(t.attributedInputResponses??[]).map(({response:e})=>e)];if(n.length===0)return!1;let r=new Set(n.map(e=>e.requestId)),i=openInputs(e.projection).find(e=>e.request.kind===`session-limit`);return i===void 0?e.turn.suspended.some(e=>e.requests.length>0&&e.requests.every(e=>r.has(e.requestId))):r.has(i.request.requestId)}function grantedApprovalKeys(e,t){let n=new Set(e.turn.grants);for(let r of e.turn.suspended)for(let e of r.requests)isApprovalRequest(e)&&n.delete(t(e)??e.action.toolName);return n}function approvingSteps(e,t){let n=e.turn.suspended.filter(e=>e.requests.length>0),r=n.length===1?resolveTextInput(n[0],t):t,i=new Map((r?.inputResponses??[]).map(e=>[e.requestId,e.optionId]));return n.filter(e=>e.requests.every(e=>i.has(e.requestId))&&e.requests.some(e=>isApprovalRequest(e)&&i.get(e.requestId)===`approve`))}function stepForRequest(e,t){return e.turn.suspended.find(e=>e.requests.some(e=>e.requestId===t))}function withdrawSignIns(e,t){return{events:e.signIns.flatMap(n=>{let r=e.projection.authorizations[n.attemptId??n.name];return r?.status===`required`?[signInWithdrawn(r,t)]:[]}),signIns:[],turn:e.turn}}function requestLimit(e,t){let n=turnPosition(e.projection);return{events:[createInputRequestedEvent({requests:[t.request],sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId}),...finishTurn(e).events],turn:e.turn}}function requireSignIn(e,t){let n=turnPosition(e.projection),r={sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId},i=[...supersededChallenges(e.signIns,t.challenges).map(e=>createAuthorizationCompletedEvent({...authorizationEventFields(e),outcome:`failed`,reason:`Superseded by a newer authorization attempt.`,...r})),...t.challenges.map(e=>createAuthorizationRequiredEvent({...authorizationEventFields(e),description:e.challenge.instructions??`Authorization required for ${e.name}`,webhookUrl:e.hookUrl,...r}))];i.push(...hold(e,{on:`input`}).events);let a=t.queued===void 0?e.turn.queued:e.turn.queued===void 0?t.queued:coalesceTurnInputs(e.turn.queued,t.queued),o=withSignIns(e.signIns,t.challenges),s=new Set([...t.callIdsByName?.values()??[]].flat()),c=e.turn.suspended.map(e=>[...stepCallIds(e)].some(e=>s.has(e))?{...e,messages:withoutCalls(e.messages,s)}:e);if(c.every((t,n)=>t===e.turn.suspended[n]))return{events:i,signIns:o,turn:{...e.turn,queued:a}};let l=settle({...e,turn:{...e.turn,queued:a,suspended:c}},{results:[]});return{commit:l.commit,events:i,signIns:o,turn:l.turn}}export{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,hasRunnableQueue,parkOnApprovals,requestLimit,requireSignIn,stepForRequest,withdrawSignIns};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SessionAuthContext } from "#channel/types.js";
|
|
2
|
+
import type { InputRequest } from "#shared/input.js";
|
|
3
|
+
import type { SessionStateMap } from "#harness/types.js";
|
|
4
|
+
/** Who approved each of the `approved` calls, by call id. */
|
|
5
|
+
export declare function approversOf(approved: readonly InputRequest[], state: SessionStateMap | undefined): Readonly<Record<string, SessionAuthContext>>;
|
|
6
|
+
/**
|
|
7
|
+
* Records who approved each of the `approved` calls, so each runs as its approver while the rest
|
|
8
|
+
* of the turn keeps the turn's own caller.
|
|
9
|
+
*/
|
|
10
|
+
export declare function setApprovedCallCallers(approved: readonly InputRequest[], state: SessionStateMap | undefined): void;
|
|
11
|
+
/** Runs `fn` as the call's approver when `callId` is an approved call; otherwise as is. */
|
|
12
|
+
export declare function runAsApprover<T>(callId: string | undefined, fn: () => T): T;
|
|
13
|
+
/** A streaming call's body runs on each `next()`, so each one runs as the approver too. */
|
|
14
|
+
export declare function iterateAsApprover<T>(callId: string | undefined, iterable: AsyncIterable<T>): AsyncIterable<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{approverOfRequest}from"./candidates.js";import{contextStorage}from"#context/container.js";import{ContextKey}from"#context/key.js";import{runAsCaller}from"#context/caller-scope.js";const ApprovedCallCallersKey=new ContextKey(`eve.approvedCallCallers`);function approversOf(e,t){let n={};for(let r of e){if(r.action===void 0)continue;let e=approverOfRequest(t,r.requestId);e!==void 0&&(n[r.action.callId]=e)}return n}function setApprovedCallCallers(e,t){let n=contextStorage.getStore();n!==void 0&&n.setVirtualContext(ApprovedCallCallersKey,new Map(Object.entries(approversOf(e,t))))}function runAsApprover(e,t){let n=e===void 0?void 0:contextStorage.getStore()?.get(ApprovedCallCallersKey)?.get(e);return n===void 0?t():runAsCaller(n,t)}async function*iterateAsApprover(e,t){let n=t[Symbol.asyncIterator]();try{for(;;){let t=await runAsApprover(e,()=>n.next());if(t.done===!0)return;yield t.value}}finally{await n.return?.()}}export{approversOf,iterateAsApprover,runAsApprover,setApprovedCallCallers};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ModelMessage, type TelemetryOptions, type ToolSet, type TypedToolResult } from "ai";
|
|
2
|
+
import type { HarnessToolMap } from "#harness/types.js";
|
|
3
|
+
import type { InputRequest } from "#shared/input.js";
|
|
4
|
+
import type { HandleEventFn } from "#harness/types.js";
|
|
5
|
+
type ToolResponsePart = Extract<ModelMessage, {
|
|
6
|
+
role: "tool";
|
|
7
|
+
}>["content"][number];
|
|
8
|
+
export interface ApprovedCallResult {
|
|
9
|
+
readonly part: Extract<ToolResponsePart, {
|
|
10
|
+
type: "tool-result";
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runs approved local calls before the model reads their results. Like the calls a model step
|
|
15
|
+
* runs inline, each streams its progress and result as it goes. The lifecycle owner places the
|
|
16
|
+
* results in the steps that made the calls.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runApprovedCalls(input: {
|
|
19
|
+
readonly requests: readonly InputRequest[];
|
|
20
|
+
readonly tools: HarnessToolMap;
|
|
21
|
+
readonly approvedTools?: ReadonlySet<string>;
|
|
22
|
+
/** The conversation the tools read as `ctx.messages`. */
|
|
23
|
+
readonly messages: readonly ModelMessage[];
|
|
24
|
+
readonly position: {
|
|
25
|
+
readonly sequence: number;
|
|
26
|
+
readonly stepIndex: number;
|
|
27
|
+
readonly turnId: string;
|
|
28
|
+
};
|
|
29
|
+
readonly publish: HandleEventFn;
|
|
30
|
+
readonly abortSignal: AbortSignal | undefined;
|
|
31
|
+
/** The step attempt's telemetry, which hears each execution as the AI SDK reports it. */
|
|
32
|
+
readonly telemetry?: TelemetryOptions;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
readonly settled: readonly ApprovedCallResult[];
|
|
35
|
+
readonly toolResults: readonly TypedToolResult<ToolSet>[];
|
|
36
|
+
}>;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{asSchema}from"ai";import{createLogger,logError}from"#internal/logging.js";import{toError}from"#shared/errors.js";import{createActionPartialEvent,createActionResultEvent}from"#protocol/message.js";import{parseJsonObject}from"#shared/json.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{createRuntimeToolResultFromValue}from"#harness/action-result-helpers.js";import{emitNestedToolActions}from"#harness/nested-actions.js";import{projectDeltaPresentation,projectResultPresentation}from"#harness/tool-presentation.js";import{isInlineAuthorizationToolResult}from"#harness/inline-tool-authorization.js";import{TOOL_EXECUTION_DENIED_MESSAGE}from"#harness/input-request-resolution.js";import{buildToolSet,recheckApprovedCall}from"#harness/tools.js";const log=createLogger(`harness.tool-loop`);async function runApprovedCalls(e){let t=buildToolSet({tools:e.tools,approvedTools:e.approvedTools}),n=e.requests.map(n=>{let r=e.tools.get(n.action.toolName),i=t[n.action.toolName];if(r?.execute===void 0||i?.execute===void 0||i.toModelOutput===void 0)throw Error(`The approved tool is no longer available. Request a new tool call and approval.`);return{request:n,definition:r,tool:i}}),r={sequence:e.position.sequence,stepIndex:e.position.stepIndex,turnId:e.position.turnId},i=await Promise.allSettled(n.map(async({request:t,definition:n,tool:i})=>{let a=[],o=[],{callId:s,toolName:c,input:l}=t.action;try{if(throwIfTurnAborted(e.abortSignal),(await asSchema(i.inputSchema).validate?.(l))?.success===!1){let t=`The approved input is no longer valid for tool "${c}". Request a new tool call and approval.`;return await e.publish(createActionResultEvent({...r,result:createRuntimeToolResultFromValue({callId:s,isError:!0,output:t,toolName:c})})),{settled:[{part:{type:`tool-result`,toolCallId:s,toolName:c,output:{type:`error-text`,value:t}}}],toolResults:o}}let t=await recheckApprovedCall(n,{abortSignal:e.abortSignal,callId:s,input:l,approvedTools:e.approvedTools});if(t.denied)return await e.publish(createActionResultEvent({...r,rejected:!0,result:{callId:s,isError:!0,kind:`tool-result`,output:{code:`TOOL_EXECUTION_DENIED`,message:t.reason??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:c}})),a.push({part:{output:{reason:t.reason,type:`execution-denied`},toolCallId:s,toolName:c,type:`tool-result`}}),{settled:a,toolResults:o};let u,d=!1,f=toolTelemetry(e.telemetry,{messages:[...e.messages],toolCall:{input:l,toolCallId:s,toolName:c,type:`tool-call`}});await f.started();let p=0;try{await f.execute(async()=>{let t=performance.now();try{let t=i.execute(l,{abortSignal:e.abortSignal,context:void 0,messages:[...e.messages],toolCallId:s});if(isAsyncIterable(t))for await(let i of t)u=i,await e.publish(createActionPartialEvent({...r,presentation:projectDeltaPresentation(n,s,parseJsonObject(l),i),result:createRuntimeToolResultFromValue({callId:s,output:i,toolName:c})}));else u=await t}finally{p=performance.now()-t}})}catch(t){await f.ended({error:t,input:l,toolCallId:s,toolName:c,type:`tool-error`},p),throwIfTurnAborted(e.abortSignal),logError(log,`tool execution failed`,t,{toolName:c,toolCallId:s}),d=!0,u=toError(t).message}d||await f.ended({input:l,output:u,toolCallId:s,toolName:c,type:`tool-result`},p);let m={input:l,output:u,toolCallId:s,toolName:c,type:`tool-result`};return o.push(m),isInlineAuthorizationToolResult(m)?{settled:a,toolResults:o}:(await emitNestedToolActions(e.publish,e.position,s),a.push({part:{output:d?{type:`error-text`,value:String(u)}:await i.toModelOutput({input:l,output:u,toolCallId:s}),toolCallId:s,toolName:c,type:`tool-result`}}),await e.publish(createActionResultEvent({...r,presentation:d?void 0:projectResultPresentation(n,s,parseJsonObject(l),u),result:createRuntimeToolResultFromValue({callId:s,isError:d,output:u,toolName:c})})),{settled:a,toolResults:o})}catch(t){throwIfTurnAborted(e.abortSignal);let n=toError(t).message;return logError(log,`approved tool failed`,t,{toolName:c,toolCallId:s}),await e.publish(createActionResultEvent({...r,result:createRuntimeToolResultFromValue({callId:s,isError:!0,output:n,toolName:c})})),{settled:[{part:{type:`tool-result`,toolCallId:s,toolName:c,output:{type:`error-text`,value:n}}}],toolResults:o}}})),a=i.find(e=>e.status===`rejected`);if(a?.status===`rejected`)throw a.reason;let o=i.flatMap(e=>e.status===`fulfilled`?[e.value]:[]);return{settled:o.flatMap(e=>e.settled),toolResults:o.flatMap(e=>e.toolResults)}}function toolTelemetry(e,t){let n=e===void 0||e.isEnabled===!1?[]:[e.integrations??[]].flat(),r={...t,callId:`approved:${t.toolCall.toolCallId}`,functionId:e?.functionId,recordInputs:e?.recordInputs,recordOutputs:e?.recordOutputs,toolContext:void 0},notify=async e=>{await Promise.allSettled(n.map(async t=>await e(t)))};return{started:()=>notify(e=>e.onToolExecutionStart?.(r)),execute:async e=>{let wrapped=e;for(let e of n){if(e.executeTool===void 0)continue;let n=wrapped;wrapped=()=>e.executeTool({...r,execute:n,toolCallId:t.toolCall.toolCallId})}await wrapped()},ended:(e,t)=>notify(n=>n.onToolExecutionEnd?.({...r,toolExecutionMs:t,toolOutput:e}))}}export{runApprovedCalls};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HarnessSession } from "#harness/types.js";
|
|
2
|
+
import type { InputRequest } from "#shared/input.js";
|
|
3
|
+
import type { JsonObject } from "#shared/json.js";
|
|
4
|
+
export { bumpSessionRuntimeUsageLimits } from "#harness/turn-tag-state.js";
|
|
5
|
+
export type SessionUsageLimitCheck = {
|
|
6
|
+
readonly kind: "within";
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: "ask";
|
|
9
|
+
readonly request: InputRequest;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: "fail";
|
|
12
|
+
readonly code: string;
|
|
13
|
+
readonly details: JsonObject;
|
|
14
|
+
readonly message: string;
|
|
15
|
+
};
|
|
16
|
+
/** Whether the session may call the model, may ask to continue, or must fail. */
|
|
17
|
+
export declare function checkSessionUsageLimit(input: {
|
|
18
|
+
readonly canAsk: boolean;
|
|
19
|
+
readonly session: HarnessSession;
|
|
20
|
+
readonly turnSequence: number;
|
|
21
|
+
}): SessionUsageLimitCheck;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{bumpSessionRuntimeUsageLimits,getSessionTokenUsage,getSessionUsageLimitViolation}from"#harness/turn-tag-state.js";import{createSessionLimitContinuationRequest}from"#harness/hitl/budget-request.js";function checkSessionUsageLimit(e){let t=getSessionUsageLimitViolation(e.session);if(t===null)return{kind:`within`};if(violationWindow(t)>0&&e.canAsk)return{kind:`ask`,request:createSessionLimitContinuationRequest({sessionId:e.session.sessionId,turnSequence:e.turnSequence,violation:t})};let n=getSessionTokenUsage(e.session);return{code:t.kind===`token-cost`?`SESSION_TOKEN_COST_LIMIT_REACHED`:`SESSION_TOKEN_LIMIT_REACHED`,details:t.kind===`token-cost`?{costUsd:n.costUsd,kind:t.kind,limitUsd:t.limitUsd,usedCostUsd:t.usedCostUsd}:{inputTokens:n.inputTokens,kind:t.kind,limit:t.limit,outputTokens:n.outputTokens,usedTokens:t.usedTokens},kind:`fail`,message:formatSessionLimitMessage(t.kind)}}function violationWindow(e){return e.kind===`token-cost`?e.limitUsd:e.limit}function formatSessionLimitMessage(e){return e===`token-cost`?`The session reached its configured model token-cost limit.`:`The session reached its configured ${e} token limit.`}export{bumpSessionRuntimeUsageLimits,checkSessionUsageLimit};
|
|
@@ -12,7 +12,6 @@ interface ApprovalCandidateAuditRecord {
|
|
|
12
12
|
readonly status: ApprovalCandidateStatus;
|
|
13
13
|
readonly createdAt: number;
|
|
14
14
|
readonly completedAt?: number;
|
|
15
|
-
readonly eventEmitted?: boolean;
|
|
16
15
|
readonly expiresAt?: number;
|
|
17
16
|
readonly reason?: string;
|
|
18
17
|
}
|
|
@@ -30,7 +29,6 @@ export interface ApprovalSettlementAuditRecord {
|
|
|
30
29
|
readonly requestId: string;
|
|
31
30
|
readonly settledAt: number;
|
|
32
31
|
readonly candidateId?: string;
|
|
33
|
-
readonly eventEmitted?: boolean;
|
|
34
32
|
}
|
|
35
33
|
export interface ActiveApprovalCandidate {
|
|
36
34
|
readonly candidateId: string;
|
|
@@ -41,7 +39,6 @@ export interface ActiveApprovalCandidate {
|
|
|
41
39
|
readonly createdAt: number;
|
|
42
40
|
readonly expiresAt: number;
|
|
43
41
|
readonly authorizationChallenges?: readonly AuthorizationChallenge[];
|
|
44
|
-
readonly pendingEventEmitted?: boolean;
|
|
45
42
|
}
|
|
46
43
|
interface ApprovalStateTransition {
|
|
47
44
|
readonly changed: boolean;
|
|
@@ -57,21 +54,6 @@ export declare function createApprovalCandidate(input: {
|
|
|
57
54
|
readonly responder: SessionAuthContext;
|
|
58
55
|
readonly state: SessionStateMap | undefined;
|
|
59
56
|
}): ApprovalStateTransition;
|
|
60
|
-
/** Marks the pending candidate event as emitted. */
|
|
61
|
-
export declare function markApprovalCandidatePendingEventEmitted(input: {
|
|
62
|
-
readonly candidateId: string;
|
|
63
|
-
readonly state: SessionStateMap | undefined;
|
|
64
|
-
}): SessionStateMap | undefined;
|
|
65
|
-
/** Marks a terminal candidate history event as emitted. */
|
|
66
|
-
export declare function markApprovalCandidateHistoryEventEmitted(input: {
|
|
67
|
-
readonly candidateId: string;
|
|
68
|
-
readonly state: SessionStateMap | undefined;
|
|
69
|
-
}): SessionStateMap | undefined;
|
|
70
|
-
/** Marks a terminal settlement event as emitted. */
|
|
71
|
-
export declare function markApprovalSettlementEventEmitted(input: {
|
|
72
|
-
readonly requestId: string;
|
|
73
|
-
readonly state: SessionStateMap | undefined;
|
|
74
|
-
}): SessionStateMap | undefined;
|
|
75
57
|
/** Marks a candidate as waiting on a private authorization challenge. */
|
|
76
58
|
export declare function markApprovalCandidateAuthorizationRequired(input: {
|
|
77
59
|
readonly authorizationChallenges: readonly AuthorizationChallenge[];
|
|
@@ -117,6 +99,15 @@ export declare function getApprovalAuditState(state: SessionStateMap | undefined
|
|
|
117
99
|
readonly candidateHistory: readonly ApprovalCandidateAuditRecord[];
|
|
118
100
|
readonly settlements: readonly ApprovalSettlementAuditRecord[];
|
|
119
101
|
};
|
|
102
|
+
export declare function sameResponder(a: Pick<SessionAuthContext, "authenticator" | "issuer" | "principalId" | "principalType">, b: Pick<SessionAuthContext, "authenticator" | "issuer" | "principalId" | "principalType">): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* The held turn moved on, steered or cancelled: the responders still checking one of its
|
|
105
|
+
* approvals stop, their candidates stale.
|
|
106
|
+
*/
|
|
107
|
+
export declare function retireActiveCandidates(state: SessionStateMap | undefined, input: {
|
|
108
|
+
readonly completedAt: number;
|
|
109
|
+
readonly reason: string;
|
|
110
|
+
}): SessionStateMap | undefined;
|
|
120
111
|
/** The full auth of whoever approved `requestId`, when it was allowed. */
|
|
121
112
|
export declare function approverOfRequest(state: SessionStateMap | undefined, requestId: string): SessionAuthContext | undefined;
|
|
122
113
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const APPROVAL_STATE_KEY=`eve.runtime.hitl.approvalState`;function createApprovalCandidate(e){let t=expireApprovalCandidates({now:e.createdAt,state:e.state}),n=readApprovalState(t);if(n.settlements[e.requestId]!==void 0)return{changed:!1,state:t};let r=e.responder;if(Object.values(n.activeCandidates).find(t=>t.requestId===e.requestId&&t.decision===e.decision&&sameResponder(t.responder,r))!==void 0)return{changed:!1,state:t};let i=n.activeCandidates[e.candidateIdPrefix]!==void 0||n.candidateHistory.some(t=>t.candidateId===e.candidateIdPrefix)?`${e.candidateIdPrefix}.${n.nextCandidateSequence.toString(36)}`:e.candidateIdPrefix;if(n.activeCandidates[i]!==void 0||n.candidateHistory.some(e=>e.candidateId===i))throw Error(`Approval candidate id collision: "${i}".`);let a={candidateId:i,createdAt:e.createdAt,decision:e.decision,expiresAt:e.expiresAt,requestId:e.requestId,responder:r,status:`pending`};return{changed:!0,state:writeApprovalState(t,{...n,activeCandidates:{...n.activeCandidates,[a.candidateId]:a},nextCandidateSequence:n.nextCandidateSequence+1})}}function markApprovalCandidateAuthorizationRequired(e){let t=readApprovalState(e.state),n=t.activeCandidates[e.candidateId];if(n===void 0)return e.state;let r={...n,authorizationChallenges:e.authorizationChallenges,expiresAt:e.expiresAt??n.expiresAt,status:`authorization-required`};return writeApprovalState(e.state,{...t,activeCandidates:{...t.activeCandidates,[e.candidateId]:r}})}function finishApprovalCandidate(e){let t=readApprovalState(e.state),n=t.activeCandidates[e.candidateId];if(n===void 0)return e.state;let r={...t.activeCandidates};return delete r[e.candidateId],writeApprovalState(e.state,{...t,activeCandidates:r,candidateHistory:[...t.candidateHistory,toCandidateAuditRecord({candidate:n,completedAt:e.completedAt,reason:e.reason,status:e.status})]})}function expireApprovalCandidates(e){let t=e.state,n=Object.values(readApprovalState(t).activeCandidates);for(let r of n)r.expiresAt>e.now||(t=finishApprovalCandidate({candidateId:r.candidateId,completedAt:e.now,state:t,status:`timed-out`}));return t}function settleAllowedCandidate(e){let t=expireApprovalCandidates({now:e.settledAt,state:e.state}),n=readApprovalState(t),r=n.activeCandidates[e.candidateId];if(r===void 0){let r=n.candidateHistory.find(t=>t.candidateId===e.candidateId);if((r&&n.settlements[r.requestId])!==void 0)return{changed:!1,state:t};throw Error(`Unknown approval candidate "${e.candidateId}".`)}return settleRequest({candidateId:r.candidateId,outcome:r.decision===`cancel`?`cancelled`:`allowed`,requestId:r.requestId,responder:r.responder,settledAt:e.settledAt,state:t})}function settleDirectApprovalResponse(e){let t=expireApprovalCandidates({now:e.settledAt,state:e.state});return settleRequest({outcome:e.outcome,requestId:e.requestId,responder:e.actor,settledAt:e.settledAt,state:t})}function getActiveApprovalCandidate(e,t){return readApprovalState(e).activeCandidates[t]}function getApprovalAuditState(e){let t=readApprovalState(e);return{activeCandidates:Object.values(t.activeCandidates),candidateHistory:t.candidateHistory,settlements:Object.values(t.settlements)}}function settleRequest(e){let t=readApprovalState(e.state);if(t.settlements[e.requestId]!==void 0)return{changed:!1,state:e.state};let n={actor:projectResponder(e.responder),...e.outcome===`allowed`&&{approver:e.responder},candidateId:e.candidateId,outcome:e.outcome,requestId:e.requestId,settledAt:e.settledAt},r={},i=[...t.candidateHistory];for(let n of Object.values(t.activeCandidates)){if(n.requestId!==e.requestId){r[n.candidateId]=n;continue}i.push(toCandidateAuditRecord({candidate:n,completedAt:e.settledAt,status:n.candidateId===e.candidateId?`allowed`:`stale`}))}let a={activeCandidates:r,candidateHistory:i,nextCandidateSequence:t.nextCandidateSequence,settlements:{...t.settlements,[e.requestId]:n}};return{changed:!0,state:writeApprovalState(e.state,a)}}function toCandidateAuditRecord(e){let{authorizationChallenges:t,responder:n,...r}=e.candidate;return{...r,completedAt:e.completedAt,responder:projectResponder(n),reason:e.reason,status:e.status}}function projectResponder(e){return{authenticator:e.authenticator,issuer:e.issuer,principalId:e.principalId,principalType:e.principalType}}function sameResponder(e,t){return e.authenticator===t.authenticator&&e.issuer===t.issuer&&e.principalId===t.principalId&&e.principalType===t.principalType}function readActiveCandidates(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,{...t,decision:t.decision===`cancel`?`cancel`:`approve`}]))}function readApprovalState(e){let t=e?.[APPROVAL_STATE_KEY];if(typeof t!=`object`||!t)return{activeCandidates:{},candidateHistory:[],nextCandidateSequence:0,settlements:{}};let n=t;return{activeCandidates:typeof n.activeCandidates==`object`&&n.activeCandidates!==null?readActiveCandidates(n.activeCandidates):{},candidateHistory:Array.isArray(n.candidateHistory)?n.candidateHistory:[],nextCandidateSequence:typeof n.nextCandidateSequence==`number`&&Number.isSafeInteger(n.nextCandidateSequence)&&n.nextCandidateSequence>=0?n.nextCandidateSequence:deriveNextCandidateSequence(n),settlements:typeof n.settlements==`object`&&n.settlements!==null?n.settlements:{}}}function deriveNextCandidateSequence(e){return Object.keys(e.activeCandidates??{}).length+(Array.isArray(e.candidateHistory)?e.candidateHistory.length:0)}function writeApprovalState(e,t){return{...e,[APPROVAL_STATE_KEY]:t}}function retireActiveCandidates(e,t){let n=e;for(let e of getApprovalAuditState(n).activeCandidates)n=finishApprovalCandidate({candidateId:e.candidateId,completedAt:t.completedAt,reason:t.reason,state:n,status:`stale`});return n}function approverOfRequest(e,t){return readApprovalState(e).settlements[t]?.approver}export{approverOfRequest,createApprovalCandidate,expireApprovalCandidates,finishApprovalCandidate,getActiveApprovalCandidate,getApprovalAuditState,markApprovalCandidateAuthorizationRequired,retireActiveCandidates,sameResponder,settleAllowedCandidate,settleDirectApprovalResponse};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{contextStorage}from"#context/container.js";import{AuthKey,SessionKey}from"#context/keys.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{buildApprovalResponseAuth,handleApprovalResponsePolicyError}from"#execution/tool-auth.js";import{suspendedSteps}from"#harness/session-machine/view.js";import{clearPendingAuthorization,getAuthorizationResult,getPendingAuthorization,isAuthorizationSignal}from"#harness/authorization.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{createApprovalCandidate,expireApprovalCandidates,finishApprovalCandidate,getActiveApprovalCandidate,getApprovalAuditState,markApprovalCandidateAuthorizationRequired,sameResponder,settleAllowedCandidate,settleDirectApprovalResponse}from"#harness/hitl/candidates.js";async function coordinateApprovalDelivery(e){let t=e.now??Date.now(),n=getApprovalAuditState(e.session.state).activeCandidates.filter(e=>e.expiresAt<=t),r=n.flatMap(e=>e.authorizationChallenges?.map(e=>e.attemptId??e.candidateId??e.name)??[]),i=expireApprovalCandidates({now:t,state:e.session.state}),a={...e.session,state:clearPendingAuthorization(i,r)},o=getApprovalAuditState(a.state),s=suspendedSteps(a.state).filter(e=>e.requests.length>0),c=new Set(s.flatMap(e=>e.requests.map(e=>e.requestId))),l=o.settlements.filter(e=>c.has(e.requestId)),u=new Set(o.settlements.map(e=>e.requestId)),d=new Set([...u].filter(e=>!c.has(e))),f=hasResponseForRequest(e.stepInput,d),p=f?removeConsumedResponses(e.stepInput,d):e.stepInput;if(f&&l.length===0&&!hasMeaningfulInput(p))return deliveryResult(a,p,`park`);if(s.length===0)return deliveryResult(a,p);let m=p,h=new Set(s.flatMap(e=>e.responseAuthRequiredRequestIds??[])),g=s.flatMap(e=>e.requests),_=new Map(g.map(e=>[e.requestId,e])),v=[],y=[],b=new Set,x=!1,S=getApprovalAuditState(a.state).activeCandidates,C=[...m?.attributedInputResponses??[],...(m?.inputResponses??[]).map(e=>({auth:void 0,response:e}))];for(let{auth:e,response:n}of C){let r=_.get(n.requestId);if(r===void 0||!isApprovalRequest(r))continue;if(!h.has(n.requestId)){let r=contextStorage.getStore(),i=e===void 0?r?.get(AuthKey)??r?.get(SessionKey)?.auth.current??null:e,o=toCandidateDecision(n.optionId),s=suspendedSteps(a.state).find(e=>e.requests.some(e=>e.requestId===n.requestId))?.requester??null;if(i!==null&&o!==void 0&&s!==null&&!sameResponder(s,i)){b.add(n.requestId),y.push(`Only the person who requested this action can respond to this approval.`);continue}if(i!==null&&o!==void 0){let e=settleDirectApprovalResponse({actor:i,outcome:o===`approve`?`allowed`:`cancelled`,requestId:n.requestId,settledAt:t,state:a.state});a={...a,state:e.state},x||=e.changed}continue}b.add(n.requestId);let i=toCandidateDecision(n.optionId);if(i===void 0)continue;let o=e===void 0?buildCallbackContext().session.auth.current:e;if(o===null){y.push(`Authentication is required to respond to this approval.`);continue}let s=createApprovalCandidate({candidateIdPrefix:approvalCandidateIdPrefix(r.requestId,o,i),createdAt:t,decision:i,expiresAt:t+6e5,requestId:r.requestId,responder:o,state:a.state});a={...a,state:s.state},x||=s.changed}let w=removeConsumedResponses(m,b);if(b.size>0)return deliveryResult(a,w,x?`continue-coordination`:`continue`,[],y);if(x)return deliveryResult(a,w,`continue`,[],y);let T=new Set(getPendingAuthorization(a.state)?.challenges.map(e=>e.name)??[]);for(let n of S){if(n.status===`authorization-required`){let e=n.authorizationChallenges??[];if(!e.some(e=>getAuthorizationResult(e.name)!==void 0)){v.push(...e.filter(e=>!T.has(e.name)));continue}}let r=_.get(n.requestId);if(r===void 0||getActiveApprovalCandidate(a.state,n.candidateId)===void 0)continue;let i=await authorizeCandidate({candidateId:n.candidateId,decision:n.decision,now:t,request:r,responder:n.responder,session:a,tools:await e.prepareTools?.(r)??e.tools});a=i.session,x||=i.didCommit,v.push(...i.challenges);let o=getApprovalAuditState(a.state).settlements.find(e=>e.requestId===n.requestId);o!==void 0&&l.push(o)}let E=appendSettledResponses(w,l);return(x||n.length>0)&&getApprovalAuditState(a.state).activeCandidates.length===0?deliveryResult(a,E,`responses-completed`):l.length>0?deliveryResult(a,E,`continue`):x?deliveryResult(a,E,`continue-coordination`):deliveryResult(a,E,v.length>0?`authorization-required`:`continue`,v)}async function authorizeCandidate(e){let t={...e.session,state:expireApprovalCandidates({now:e.now,state:e.session.state})};if(getActiveApprovalCandidate(t.state,e.candidateId)===void 0)return{challenges:[],didCommit:!1,session:t};let n=e.tools.get(e.request.action.toolName)?.approval,r=n!==void 0&&typeof n!=`function`?n.response:void 0;if(r===void 0)return failCandidate({...e,reason:`Approval authorization is temporarily unavailable. Please try again.`,session:t});try{let n=buildCallbackContext(),i=await withAuthorizerTimeout(r({auth:buildApprovalResponseAuth({responder:e.responder,scope:e.candidateId}),request:{callId:e.request.action.callId,requestId:e.request.requestId,principal:suspendedSteps(t.state).find(t=>t.requests.some(t=>t.requestId===e.request.requestId))?.requester??null,toolInput:e.request.action.input,toolName:e.request.action.toolName},response:{decision:e.decision,principal:e.responder},session:{id:n.session.id,initiator:n.session.auth.initiator,parent:n.session.parent,turn:n.session.turn}}));if(i.status===`rejected`)return t={...t,state:finishApprovalCandidate({candidateId:e.candidateId,completedAt:e.now,reason:i.reason,state:t.state,status:`rejected`})},{challenges:[],didCommit:!0,session:t};if(i.status!==`allowed`)return failCandidate({...e,session:t});let a=settleAllowedCandidate({candidateId:e.candidateId,settledAt:e.now,state:t.state});return{challenges:[],didCommit:a.changed,session:{...t,state:a.state}}}catch(n){let r=await handleApprovalResponsePolicyError(n).catch(()=>void 0);if(isAuthorizationSignal(r)){let n=r.challenges.map(e=>Date.parse(e.challenge.expiresAt??``)).filter(Number.isFinite).sort((e,t)=>e-t)[0];return t={...t,state:markApprovalCandidateAuthorizationRequired({authorizationChallenges:r.challenges.map(t=>({...t,candidateId:e.candidateId})),candidateId:e.candidateId,expiresAt:n,state:t.state})},{challenges:r.challenges.map(t=>({...t,candidateId:e.candidateId})),didCommit:!0,session:t}}return failCandidate({...e,session:t})}}function failCandidate(e){let t=e.reason??`We couldn’t verify your response. Please try again.`;return{challenges:[],didCommit:!0,session:{...e.session,state:finishApprovalCandidate({candidateId:e.candidateId,completedAt:e.now,reason:t,state:e.session.state,status:`failed`})}}}function hasResponseForRequest(e,t){return e?.attributedInputResponses?.some(({response:e})=>t.has(e.requestId))===!0||e?.inputResponses?.some(e=>t.has(e.requestId))===!0}function hasMeaningfulInput(e){return e?.message!==void 0||(e?.attributedInputResponses?.length??0)>0||(e?.inputResponses?.length??0)>0||(e?.runtimeActionResults?.length??0)>0}function appendSettledResponses(e,t){if(t.length===0)return e;let n=new Set([...(e?.inputResponses??[]).map(e=>e.requestId),...(e?.attributedInputResponses??[]).map(({response:e})=>e.requestId)]),r=t.filter(e=>!n.has(e.requestId));return r.length===0?e:{...e,inputResponses:[...e?.inputResponses??[],...r.map(e=>({optionId:e.outcome===`allowed`?`approve`:`cancel`,requestId:e.requestId}))]}}function removeConsumedResponses(e,t){if(e===void 0)return;let n=(e.attributedInputResponses??[]).filter(({response:e})=>!t.has(e.requestId)),r=[...(e.inputResponses??[]).filter(e=>!t.has(e.requestId)),...n.map(({response:e})=>e)];return{...e,attributedInputResponses:void 0,inputResponses:r}}function deliveryResult(e,t,n=`continue`,r=[],i=[]){return{challenges:r,feedback:i,kind:n,session:e,stepInput:t}}function toCandidateDecision(e){if(e===`approve`)return`approve`;if(e===`cancel`||e===`deny`)return`cancel`}function approvalCandidateIdPrefix(e,t,n){let r=[t.authenticator,t.issuer??``,t.principalType,t.principalId].join(`:`),i=`${encodeCandidateIdPart(e)}.${encodeCandidateIdPart(r)}`;return n===`approve`?i:`${i}.${encodeCandidateIdPart(n)}`}function encodeCandidateIdPart(e){return Array.from(e,e=>e.codePointAt(0).toString(36)).join(`-`)}async function withAuthorizerTimeout(e){let t;try{return await Promise.race([Promise.resolve(e),new Promise((e,n)=>{t=setTimeout(()=>n(Error(`Approval response authorizer timed out.`)),1e4)})])}finally{t!==void 0&&clearTimeout(t)}}export{coordinateApprovalDelivery};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { UserContent } from "ai";
|
|
2
|
+
import type { StepInput } from "#harness/types.js";
|
|
3
|
+
import type { InputResponse } from "#shared/input.js";
|
|
4
|
+
import type { SuspendedStep } from "#harness/session-machine/state.js";
|
|
5
|
+
import type { SessionView } from "#harness/session-machine/view.js";
|
|
6
|
+
/**
|
|
7
|
+
* The delivery a step answers with: input queued behind earlier work joins it, unless the
|
|
8
|
+
* runtime still runs calls (queued input waits for them). A stale answer, to a request that
|
|
9
|
+
* already closed, never authorizes anything: a stale session-limit answer is dropped, and
|
|
10
|
+
* any other becomes plain text the model reads.
|
|
11
|
+
*/
|
|
12
|
+
export declare function deliver(view: SessionView, input: StepInput | undefined, options: {
|
|
13
|
+
readonly takeQueued: boolean;
|
|
14
|
+
}): {
|
|
15
|
+
readonly input?: StepInput;
|
|
16
|
+
readonly displayMessage?: string | UserContent;
|
|
17
|
+
readonly takeQueued: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type ResolvedStepInput = StepInput & {
|
|
20
|
+
readonly messageConsumed?: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Plain text answers the only pending batch, unless a response policy must decide it. A channel
|
|
24
|
+
* that wraps the typed text in an envelope for the model attaches the text itself to answer with.
|
|
25
|
+
* The answer consumes the message and the context the channel sent about it: the model reads
|
|
26
|
+
* neither.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveTextInput(batch: Pick<SuspendedStep, "requests" | "responseAuthRequiredRequestIds">, stepInput: StepInput | undefined): ResolvedStepInput | undefined;
|
|
29
|
+
export declare function canonicalize(responses: readonly InputResponse[]): readonly InputResponse[];
|
|
30
|
+
export declare function hasInput(input: StepInput | undefined): boolean;
|
|
31
|
+
export declare function isEmptyInput(input: StepInput): boolean;
|
|
32
|
+
export declare function withoutResponses(input: ResolvedStepInput | undefined): StepInput | undefined;
|
|
33
|
+
/** The turn's own input: the message a plain-text answer didn't consume, and its context. */
|
|
34
|
+
export declare function turnInputOnly(input: ResolvedStepInput | undefined): StepInput | undefined;
|
|
35
|
+
/** What of the input isn't the turn's: answers, and the output the session asks for. */
|
|
36
|
+
export declare function withoutTurnInput(input: ResolvedStepInput | undefined): ResolvedStepInput;
|
|
37
|
+
export declare function compactInput(input: ResolvedStepInput | undefined): ResolvedStepInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{attachClientContext,readClientContext}from"#internal/client-context.js";import{readAnswerText}from"#internal/input-text.js";import{resolveTextToResponses}from"#channel/resolve-text.js";import{coalesceTurnInputs}from"#harness/messages.js";import{ownOpenRequestIds}from"#harness/session-machine/transitions.js";import{convertStaleResponsesToUserMessage,dropStaleSessionLimitContinuationResponses}from"#harness/hitl/stale-responses.js";function deliver(e,t,n){let r=n.takeQueued?e.turn.queued:void 0,i=r===void 0?t:t===void 0?r:coalesceTurnInputs(r,t),a=new Set([...ownOpenRequestIds(e),...e.turn.suspended.flatMap(e=>e.requests.map(e=>e.requestId))]),o=new Map(Object.values(e.projection.inputs).map(e=>[e.request.requestId,e.request])),s=convertStaleResponsesToUserMessage({pendingRequestIds:a,requests:o,stepInput:dropStaleSessionLimitContinuationResponses({pendingRequestIds:a,stepInput:i})});return s.kind===`converted`?{displayMessage:s.displayMessage,input:s.stepInput,takeQueued:n.takeQueued}:{input:s.stepInput,takeQueued:n.takeQueued}}function resolveTextInput(e,t){let n=readAnswerText(t);if(t===void 0||n===void 0)return t;let r=new Set(e.requests.map(e=>e.requestId));if(t.inputResponses?.some(e=>r.has(e.requestId)))return t;let i=new Set(e.responseAuthRequiredRequestIds??[]),a=resolveTextToResponses(n,e.requests.filter(e=>!i.has(e.requestId)));return a.length===0?t:compactInput({...t,context:void 0,inputResponses:[...t.inputResponses??[],...a],message:void 0,messageConsumed:!0})}function canonicalize(e){let t=new Map;for(let n of e)t.set(n.requestId,n);return[...t.values()]}function hasInput(e){return e?.message!==void 0||(e?.inputResponses?.length??0)>0}function isEmptyInput(e){return Object.keys(compactInput(e)).length===0}function withoutResponses(e){if(e===void 0)return;let{attributedInputResponses:t,inputResponses:n,messageConsumed:r,...i}=e;return i}function turnInputOnly(e){if(e===void 0)return;let t={};(e.context?.length??0)>0&&(t.context=e.context),e.message!==void 0&&e.messageConsumed!==!0&&(t.message=e.message);let n=attachClientContext(t,readClientContext(e));return isEmptyInput(n)?void 0:n}function withoutTurnInput(e){let t={};return(e?.inputResponses?.length??0)>0&&(t.inputResponses=e.inputResponses),e?.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),t}function compactInput(e){if(e===void 0)return{};let t={};return(e.context?.length??0)>0&&(t.context=e.context),(e.inputResponses?.length??0)>0&&(t.inputResponses=e.inputResponses),e.message!==void 0&&(t.message=e.message),e.messageConsumed===!0&&(t.messageConsumed=!0),e.outputSchema!==void 0&&(t.outputSchema=e.outputSchema),attachClientContext(t,readClientContext(e))}export{canonicalize,compactInput,deliver,hasInput,isEmptyInput,resolveTextInput,turnInputOnly,withoutResponses,withoutTurnInput};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ModelMessage } from "ai";
|
|
2
|
+
import type { resolveInlineAuthorizationInterrupt } from "#harness/inline-tool-authorization.js";
|
|
3
|
+
import type { StepCoordinates } from "#harness/session-machine/view.js";
|
|
4
|
+
import type { Step } from "#harness/step/context.js";
|
|
5
|
+
import type { HarnessSessionBase, StepResult } from "#harness/types.js";
|
|
6
|
+
import type { RuntimeWorkflowTaskRequest } from "#shared/action-types.js";
|
|
7
|
+
import type { InputRequest } from "#shared/input.js";
|
|
8
|
+
export { acceptHumanInput, admitApprovedWork, dispatchApprovedWorkflows, hasApprovedWork, runApprovedLocalCalls, type ApprovedWork, type HumanInputIntake, } from "./intake.js";
|
|
9
|
+
export { extractToolApprovalInputRequests } from "#harness/input-extraction.js";
|
|
10
|
+
export { hasRunnableQueue } from "./approvals.js";
|
|
11
|
+
/**
|
|
12
|
+
* A model step made calls that need a person's approval: the step parks on them beside any
|
|
13
|
+
* runtime calls it made. The turn holds for the answers, unless the runtime runs calls for it
|
|
14
|
+
* meanwhile, or queued input can already run.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parkOnApprovals(step: Step, input: {
|
|
17
|
+
readonly event: StepCoordinates;
|
|
18
|
+
readonly messages: readonly ModelMessage[];
|
|
19
|
+
readonly requests: readonly InputRequest[];
|
|
20
|
+
readonly tasks: readonly RuntimeWorkflowTaskRequest[];
|
|
21
|
+
/** The step made calls the runtime runs, so the turn waits on them instead. */
|
|
22
|
+
readonly waitsOnRuntime: boolean;
|
|
23
|
+
}): Promise<StepResult>;
|
|
24
|
+
/**
|
|
25
|
+
* A call the model step ran needs a sign-in: the calls that need it stop, and the model calls
|
|
26
|
+
* them again once it completes.
|
|
27
|
+
*/
|
|
28
|
+
export declare function stopForToolSignIn(step: Step, interrupt: NonNullable<ReturnType<typeof resolveInlineAuthorizationInterrupt>>): Promise<StepResult>;
|
|
29
|
+
/**
|
|
30
|
+
* The gate before each model call. A spent budget asks whether to continue when someone can
|
|
31
|
+
* answer, and fails the session otherwise. `messages` are the step's: they park with the prompt,
|
|
32
|
+
* so the input that triggered it survives into the turn that resumes.
|
|
33
|
+
*/
|
|
34
|
+
export declare function enforceBudget(step: Step, messages: readonly ModelMessage[]): Promise<StepResult | undefined>;
|
|
35
|
+
/**
|
|
36
|
+
* What a model call needs from the approvals: the keys `once()` approvals granted, and a note on
|
|
37
|
+
* the calls still awaiting approval, which a message may revise.
|
|
38
|
+
*/
|
|
39
|
+
export declare function humanInputContext(step: Step): {
|
|
40
|
+
readonly approvedTools: ReadonlySet<string>;
|
|
41
|
+
readonly pendingApprovalsNote?: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Drops what a cleared context owned: sign-in attempts and responders' approval progress. `clear`
|
|
45
|
+
* reported each close; relay routes for live tasks stay.
|
|
46
|
+
*/
|
|
47
|
+
export declare function discardClearedHumanInput<T extends HarnessSessionBase>(session: T): T;
|
|
48
|
+
/** The cancelled turn's responders stop checking its approvals: their candidates stale. */
|
|
49
|
+
export declare function retireCancelledCandidates<T extends HarnessSessionBase>(session: T): T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{renderPendingApprovalsInstruction}from"./approval-prompt.js";import{grantedApprovalKeys,hasRunnableQueue,parkOnApprovals as parkOnApprovals$1,requestLimit,requireSignIn}from"./approvals.js";import{retireActiveCandidates}from"./candidates.js";import{checkSessionUsageLimit}from"./budget.js";import{acceptHumanInput,admitApprovedWork,dispatchApprovedWorkflows,hasApprovedWork,holdForInput,runApprovedLocalCalls}from"./intake.js";import{AuthKey,SessionKey}from"#context/keys.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{fail}from"#harness/session-machine/transitions.js";import{clearPendingAuthorization}from"#harness/authorization.js";import{buildResponseAuthorizationTools}from"#context/build-dynamic-tools.js";import{extractToolApprovalInputRequests}from"#harness/input-extraction.js";async function parkOnApprovals(e,t){let n=parkOnApprovals$1(e.view(),{event:t.event,messages:t.messages,requests:t.requests,tasks:t.tasks,requester:currentRequester(e),responseAuthRequiredRequestIds:responsePolicyRequestIds(e,t.requests)});return await e.apply(n,[...e.session.history,...n.commit??[]]),t.waitsOnRuntime?{next:null,session:e.session}:hasRunnableQueue(e.view())?{next:e.runStep,session:e.session}:holdForInput(e)}async function stopForToolSignIn(e,t){return e.session={...e.session,history:validateHarnessModelMessages(t.history)},await e.apply(requireSignIn(e.view(),{callIdsByName:t.callIdsByName,challenges:t.challenges}),e.session.history),{held:{kind:`request`},next:null,session:e.session}}async function enforceBudget(e,t){let n=checkSessionUsageLimit({canAsk:e.emit!==void 0&&e.config.capabilities?.requestInput===!0,session:e.session,turnSequence:e.position().sequence});if(n.kind!==`within`)return n.kind===`ask`?(e.session={...e.session,history:validateHarnessModelMessages([...t])},await e.apply(requestLimit(e.view(),{request:n.request}),e.session.history),{next:null,session:e.session}):(await e.apply(fail(e.view(),{code:n.code,details:n.details,message:n.message,terminal:{sessionId:e.session.sessionId}})),{next:{done:!0,output:``},session:e.session})}function humanInputContext(e){let t=e.view(),n=responseTools(e);return{approvedTools:grantedApprovalKeys(t,e=>n.get(e.action.toolName)?.approvalKey?.(e.action.input)),pendingApprovalsNote:renderPendingApprovalsInstruction(t.turn.suspended.flatMap(e=>e.requests))}}function discardClearedHumanInput(e){let{"eve.runtime.hitl.approvalState":t,...n}=clearPendingAuthorization(e.state)??{};return{...e,state:Object.keys(n).length>0?n:void 0}}function responseTools(e){return buildResponseAuthorizationTools({authoredTools:e.config.tools,context:e.ctx})}function responsePolicyRequestIds(e,t){let n=responseTools(e);return t.filter(e=>{let t=n.get(e.action.toolName)?.approval;return t!==void 0&&typeof t!=`function`&&t.response!==void 0}).map(e=>e.requestId)}function currentRequester(e){return e.ctx?.get(AuthKey)??e.ctx?.get(SessionKey)?.auth.current??null}function retireCancelledCandidates(e){return{...e,state:retireActiveCandidates(e.state,{completedAt:Date.now(),reason:`Cancelled.`})}}export{acceptHumanInput,admitApprovedWork,discardClearedHumanInput,dispatchApprovedWorkflows,enforceBudget,extractToolApprovalInputRequests,hasApprovedWork,hasRunnableQueue,humanInputContext,parkOnApprovals,retireCancelledCandidates,runApprovedLocalCalls,stopForToolSignIn};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { SuspendedStep } from "#harness/session-machine/view.js";
|
|
2
|
+
import { type Step } from "#harness/step/context.js";
|
|
3
|
+
import type { HarnessToolMap, StepInput, StepResult } from "#harness/types.js";
|
|
4
|
+
import type { InstrumentationAttempt } from "#instrumentation/runtime.js";
|
|
5
|
+
/**
|
|
6
|
+
* What a delivery does before its turn runs. `stop` ends the step: the answers left nothing to
|
|
7
|
+
* run yet, so the turn holds, or a responder must sign in first. `run` carries the turn's input,
|
|
8
|
+
* without the answers the session took, and the approved work that runs once the turn opens.
|
|
9
|
+
*/
|
|
10
|
+
export type HumanInputIntake = {
|
|
11
|
+
readonly kind: "stop";
|
|
12
|
+
readonly result: StepResult;
|
|
13
|
+
} | {
|
|
14
|
+
readonly kind: "run";
|
|
15
|
+
readonly input: StepInput | undefined;
|
|
16
|
+
/** The message the turn receives, as the stream shows it. */
|
|
17
|
+
readonly message?: StepInput["message"];
|
|
18
|
+
/** A plain-text answer consumed the message, so the model never reads it. */
|
|
19
|
+
readonly consumedMessage: boolean;
|
|
20
|
+
/** The delivery carries input for a turn. */
|
|
21
|
+
readonly opensTurn: boolean;
|
|
22
|
+
readonly approved: ApprovedWork;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* What the delivery decided: the session-limit answer, and the tools approved calls run with.
|
|
26
|
+
* The calls themselves wait in their suspended steps until the turn's next model step.
|
|
27
|
+
*/
|
|
28
|
+
export interface ApprovedWork {
|
|
29
|
+
readonly limit?: {
|
|
30
|
+
readonly granted: boolean;
|
|
31
|
+
};
|
|
32
|
+
/** The tools a parked step's calls run with: those of the step that asked. */
|
|
33
|
+
readonly toolsOf: (step: SuspendedStep | undefined) => HarnessToolMap;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Answers what the session asked: approval answers pass the response policies, and the session
|
|
37
|
+
* decides which parked steps they resolve. Runs before the delivery joins its turn, so approved
|
|
38
|
+
* calls get the tools of the step that asked.
|
|
39
|
+
*/
|
|
40
|
+
export declare function acceptHumanInput(step: Step, input: StepInput | undefined, options: {
|
|
41
|
+
readonly takeQueued: boolean;
|
|
42
|
+
}): Promise<HumanInputIntake>;
|
|
43
|
+
/**
|
|
44
|
+
* Admits what a delivery decided before its turn calls the model: a session-limit answer grants a
|
|
45
|
+
* fresh budget or ends the turn tree, and a step its answers completed, as denials do, commits.
|
|
46
|
+
*/
|
|
47
|
+
export declare function admitApprovedWork(step: Step, work: ApprovedWork): Promise<void>;
|
|
48
|
+
/** Whether a suspended step holds approved calls that haven't run. */
|
|
49
|
+
export declare function hasApprovedWork(step: Step): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Approved workflow and agent calls join the runs their steps wait on, once the step has started
|
|
52
|
+
* and before its budget check. Returns whether any did: the turn then waits on the runtime, and
|
|
53
|
+
* approved local calls run after their results arrive.
|
|
54
|
+
*/
|
|
55
|
+
export declare function dispatchApprovedWorkflows(step: Step, work: ApprovedWork): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Runs approved local calls once the step has started and its budget allows it, as the AI SDK ran
|
|
58
|
+
* them before the model read their results: each with the tools of the step that asked, as
|
|
59
|
+
* whoever approved it, and in the step's first attempt. A call that needs a sign-in holds the
|
|
60
|
+
* turn.
|
|
61
|
+
*/
|
|
62
|
+
export declare function runApprovedLocalCalls(step: Step, work: ApprovedWork, setAttemptScope: (scope: InstrumentationAttempt | undefined) => void): Promise<StepResult | undefined>;
|
|
63
|
+
/**
|
|
64
|
+
* The held turn holds on, for a person to act on its sign-in, approval, or the session-limit
|
|
65
|
+
* prompt; the session resumes it when they do.
|
|
66
|
+
*/
|
|
67
|
+
export declare function holdForInput(step: Step): Promise<StepResult>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{deliver,turnInputOnly,withoutTurnInput}from"./delivery.js";import{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,requireSignIn,stepForRequest,withdrawSignIns}from"./approvals.js";import{getApprovalAuditState,retireActiveCandidates}from"./candidates.js";import{approversOf,setApprovedCallCallers}from"./approved-call-callers.js";import{runApprovedCalls}from"./approved-calls.js";import{coordinateApprovalDelivery}from"./coordinator.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{activeTurnId}from"#harness/session-machine/view.js";import{bumpSessionRuntimeUsageLimits}from"#harness/turn-tag-state.js";import{collectDeferredCalls}from"#harness/coordination.js";import{approvedCalls,completeSignIn,hold,settle}from"#harness/session-machine/transitions.js";import{stepStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{SessionLimitDeclinedError}from"#harness/turn-cancellation.js";import{resolveInlineAuthorizationInterrupt}from"#harness/inline-tool-authorization.js";import{buildResponseAuthorizationTools}from"#context/build-dynamic-tools.js";import{openTurn}from"#harness/step/context.js";import{prepareTurnInput}from"#harness/step/intake.js";import{placeTurnInput}from"#harness/step/prompt.js";async function acceptHumanInput(e,t,n){let{config:r,ctx:i}=e,a=r.signInCompletions??[];a.length>0&&await e.apply(completeSignIn(e.view(),{completions:a}));let o=deliver(e.view(),t,n),s=t?.message!==void 0||o.displayMessage!==void 0?await withdrawSteeredSignIns(e,o.input):o.input,c=new Map,l,restoreTools=async t=>{let n=t?.event??e.position(),a=`${n.turnId}:${n.stepIndex}`,o=c.get(a);if(o!==void 0&&l===a)return o;t!==void 0&&await r.prepareApprovalTurn?.(t.event),i!==void 0&&await r.resolveStepDynamicTools?.({ctx:i,event:stepStartedForResolvers({modelId:e.session.agent.modelReference?.id??`dynamic`,sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId}),messages:e.projectHistory(e.session.history)});let s=buildResponseAuthorizationTools({authoredTools:r.tools,context:i});return c.set(a,s),l=a,s},toolsOf=e=>(e&&c.get(`${e.event.turnId}:${e.event.stepIndex}`))??r.tools,u=e.view().signIns,d=await coordinateApprovalDelivery({session:e.session,stepInput:s,tools:r.tools,prepareTools:t=>restoreTools(stepForRequest(e.view(),t.requestId))});e.session=d.session;for(let t of approvingSteps(e.view(),d.stepInput))await restoreTools(t);let f=answer(e.view(),{approvalKey:t=>toolsOf(stepForRequest(e.view(),t.requestId)).get(t.action.toolName)?.approvalKey?.(t.action.input),delivery:d.stepInput,policy:{...d,audit:getApprovalAuditState(e.session.state),challengesAtStart:u},takeQueued:o.takeQueued});for(let t of f.resolved)await e.instrumentation?.publishInputResolutions({batch:t,sessionId:e.session.sessionId});await e.apply(f);let stop=e=>({kind:`stop`,result:e});switch(f.next){case`park`:return e.view().projection.activeTurnId===void 0?stop({next:null,session:e.session}):stop(await holdForInput(e));case`repeat`:return stop({next:e.runStep,session:e.session});case`sign-in`:return await e.apply(requireSignIn(e.view(),{challenges:d.challenges,queued:d.stepInput})),stop(held(e));case`defer-message`:{if(approvedCalls(e.view().turn).length>0){let t=turnInputOnly(f.input);return t!==void 0&&await e.apply(deferInput(e.view(),t)),stop({next:null,session:e.session})}let t=await prepareTurnInput(e,f.input,{consumedMessage:!1}),n=await openTurn(e,{input:[...t.ephemeral,...t.messages],message:o.displayMessage??f.input?.message});return n===void 0?(e.session={...e.session,history:validateHarnessModelMessages(placeTurnInput(e,e.session.history,t))},stop(await holdForInput(e))):stop(n)}}for(let t of e.view().turn.suspended)(t.approved?.length??0)>0&&await restoreTools(t);let p=f.resolved.some(e=>e.inputs.some(e=>e.request.kind===`tool-approval`)&&e.inputs.every(e=>e.response!==void 0))||approvedCalls(e.view().turn).length>0?turnInputOnly(f.input):void 0;return p!==void 0&&await e.apply(deferInput(e.view(),p)),{approved:{limit:f.limit,toolsOf},consumedMessage:f.consumedMessage===!0,input:p===void 0?f.input:withoutTurnInput(f.input),message:f.consumedMessage===!0||p!==void 0?void 0:o.displayMessage??o.input?.message,kind:`run`,opensTurn:hasTurnInput(o.input)||hasTurnInput(d.stepInput)}}async function admitApprovedWork(e,t){if(t.limit!==void 0){if(!t.limit.granted)throw new SessionLimitDeclinedError;e.session=bumpSessionRuntimeUsageLimits(e.session)}await e.apply(settle(e.view(),{results:[]}))}function hasApprovedWork(e){return approvedCalls(e.view().turn).length>0}async function dispatchApprovedWorkflows(e,t){let n=[],r=[];for(let i of e.view().turn.suspended){let a=t.toolsOf(i),o=(i.approved??[]).filter(e=>a.get(e.action.toolName)?.workflowId!==void 0);if(o.length===0)continue;r.push(...o);let s=collectDeferredCalls({session:e.session,toolCalls:o.map(({action:e})=>({input:e.input,toolCallId:e.callId,toolName:e.toolName})),tools:a,turnId:i.event.turnId});e.session=s.session,n.push(...s.workflowRequests)}return n.length!==0&&(await e.apply(dispatch(e.view(),{approvers:approversOf(r,e.session.state),tasks:n})),!0)}async function runApprovedLocalCalls(e,t,n){let r=e.view().turn.suspended.map(e=>{let n=t.toolsOf(e);return{requests:(e.approved??[]).filter(e=>n.get(e.action.toolName)?.workflowId===void 0),tools:n}}),i=r.flatMap(({requests:e})=>e);e.frameworkToolNames=new Set(r.flatMap(({tools:e})=>[...e].filter(([,e])=>e.frameworkTool===!0).map(([e])=>e))),setApprovedCallCallers(i,e.session.state);let a=e.position(),o=i.length===0?void 0:e.instrumentation?.prepareAttempt({isFrameworkTool:t=>e.frameworkToolNames.has(t),attemptIndex:0,stepIndex:a.stepIndex,turnId:activeTurnId(a)});o!==void 0&&n(o.scope);let s=await Promise.all(r.map(async({requests:t,tools:n})=>t.length===0?{settled:[],toolResults:[]}:await runApprovedCalls({abortSignal:e.config.abortSignal,approvedTools:grantedApprovalKeys(e.view(),e=>n.get(e.action.toolName)?.approvalKey?.(e.action.input)),messages:e.projectHistory(e.session.history),position:e.position(),publish:e.publish,requests:t,telemetry:o?.telemetry,tools:n})));await e.apply(settle(e.view(),{results:s.flatMap(e=>e.settled)}));let c=resolveInlineAuthorizationInterrupt({messages:[],toolResults:s.flatMap(e=>e.toolResults)});if(c!==void 0)return await e.apply(requireSignIn(e.view(),{callIdsByName:c.callIdsByName,challenges:c.challenges}),e.session.history),held(e)}const STEERED_SIGN_IN_REASON=`Cancelled because a new message arrived.`;async function holdForInput(e){return await e.apply(hold(e.view(),{on:`input`})),held(e)}function held(e){return{held:{kind:`request`},next:null,session:e.session}}async function withdrawSteeredSignIns(e,t){let n=[...new Set(e.view().signIns.map(e=>e.name))];return e.session={...e.session,state:retireActiveCandidates(e.session.state,{completedAt:Date.now(),reason:STEERED_SIGN_IN_REASON})},n.length===0?t:(await e.apply(withdrawSignIns(e.view(),STEERED_SIGN_IN_REASON)),{...t,context:[...t?.context??[],`Sign-in to ${n.join(`, `)} was cancelled because the user sent a new message instead. Ask to sign in again only if the new message still needs it.`]})}function hasTurnInput(e){return e===void 0?!1:e.message!==void 0||(e.inputResponses?.length??0)>0}export{acceptHumanInput,admitApprovedWork,dispatchApprovedWorkflows,hasApprovedWork,holdForInput,runApprovedLocalCalls};
|