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,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UserContent } from "ai";
|
|
2
2
|
import type { StepInput } from "#harness/types.js";
|
|
3
|
+
import type { InputRequest } from "#shared/input.js";
|
|
3
4
|
type StaleResponseConversion = {
|
|
4
5
|
readonly kind: "unchanged";
|
|
5
6
|
readonly stepInput?: StepInput;
|
|
@@ -31,14 +32,15 @@ export declare function dropStaleSessionLimitContinuationResponses(input: {
|
|
|
31
32
|
* Responses for pending requests stay structured; stale responses become
|
|
32
33
|
* plain user-message text. A stale response never reaches structured HITL
|
|
33
34
|
* processing, so a stale approval cannot authorize an earlier tool call.
|
|
34
|
-
* Request details
|
|
35
|
+
* Request details the session still knows are best-effort model context.
|
|
35
36
|
*
|
|
36
37
|
* Assumes {@link dropStaleSessionLimitContinuationResponses} already ran:
|
|
37
38
|
* stale continuation answers must never reach this conversion.
|
|
38
39
|
*/
|
|
39
40
|
export declare function convertStaleResponsesToUserMessage(input: {
|
|
40
|
-
readonly history: readonly ModelMessage[];
|
|
41
41
|
readonly pendingRequestIds: ReadonlySet<string>;
|
|
42
|
+
/** Requests the session still knows, by id, closed ones included. */
|
|
43
|
+
readonly requests: ReadonlyMap<string, InputRequest>;
|
|
42
44
|
readonly stepInput?: StepInput;
|
|
43
45
|
}): StaleResponseConversion;
|
|
44
46
|
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{appendUserContent,normalizeUserContent}from"#harness/messages.js";import{isSessionLimitContinuationRequestId}from"#harness/hitl/budget-request.js";function dropStaleSessionLimitContinuationResponses(e){if(e.stepInput===void 0)return;let t=e.stepInput.inputResponses??[],n=e.stepInput.attributedInputResponses??[],keep=t=>e.pendingRequestIds.has(t)||!isSessionLimitContinuationRequestId(t),r=t.filter(e=>keep(e.requestId)),i=n.filter(({response:e})=>keep(e.requestId));if(r.length===t.length&&i.length===n.length)return e.stepInput;let{attributedInputResponses:a,inputResponses:o,...s}=e.stepInput,c=s;return r.length>0&&(c.inputResponses=r),i.length>0&&(c.attributedInputResponses=i),c}function convertStaleResponsesToUserMessage(e){if(e.stepInput===void 0)return{kind:`unchanged`};let t=e.stepInput.inputResponses??[],n=e.stepInput.attributedInputResponses??[];if(t.length===0&&n.length===0)return{kind:`unchanged`,stepInput:e.stepInput};let r=[],i=[],a=[];for(let n of t)(e.pendingRequestIds.has(n.requestId)?r:a).push(n);for(let t of n)e.pendingRequestIds.has(t.response.requestId)?i.push(t):a.push(t.response);if(a.length===0)return{kind:`unchanged`,stepInput:e.stepInput};let{requests:o}=e,s=appendOptionalUserContent(e.stepInput.message,formatModelMessage(a,o)),c=appendOptionalUserContent(e.stepInput.message,formatDisplayMessage(a,o)),{attributedInputResponses:l,inputResponses:u,...d}=e.stepInput,f={...d,message:s};return r.length>0&&(f.inputResponses=r),i.length>0&&(f.attributedInputResponses=i),{displayMessage:c,kind:`converted`,stepInput:f}}function formatModelMessage(e,t){let n=e.map(e=>{let n=t.get(e.requestId),r=n?.options?.find(t=>t.id===e.optionId),i={};if(e.optionId!==void 0&&(i.optionId=e.optionId),r!==void 0){let e={id:r.id,label:r.label};r.description!==void 0&&(e.description=r.description),i.selectedOption=e}e.text!==void 0&&(i.text=e.text);let a={requestId:e.requestId,response:i};return n?.kind===`tool-approval`&&(a.prompt=n.prompt,a.requestType=`approval`,a.toolName=n.action.toolName),a});return[`The user submitted the following response to an earlier interactive prompt.`,`Treat it as new input at the current point in the conversation and decide whether it is still relevant. This does not authorize an earlier action; request approval again if that action is still needed.`,JSON.stringify(n,null,2)].join(`
|
|
2
|
+
`)}function formatDisplayMessage(e,t){return e.map(e=>e.text!==void 0&&e.text.length>0?e.text:t.get(e.requestId)?.options?.find(t=>t.id===e.optionId)?.label??e.optionId??`Response to an earlier interactive prompt`).join(`
|
|
3
|
+
`)}function appendOptionalUserContent(e,t){let n=normalizeUserContent(e);return n===void 0?t:appendUserContent({appended:t,existing:n})}export{convertStaleResponsesToUserMessage,dropStaleSessionLimitContinuationResponses};
|
|
@@ -11,5 +11,9 @@ export declare function resolveInlineAuthorizationInterrupt(input: {
|
|
|
11
11
|
readonly toolResults: readonly TypedToolResult<ToolSet>[] | undefined;
|
|
12
12
|
}): {
|
|
13
13
|
readonly challenges: AuthorizationSignal["challenges"];
|
|
14
|
+
/** The calls each sign-in stopped, by the challenge's connection name. */
|
|
15
|
+
readonly callIdsByName: ReadonlyMap<string, readonly string[]>;
|
|
14
16
|
readonly history: ModelMessage[];
|
|
15
17
|
} | undefined;
|
|
18
|
+
/** Drops the given calls and their results, keeping protocol-complete sibling calls. */
|
|
19
|
+
export declare function withoutCalls(messages: readonly ModelMessage[], interruptedCallIds: ReadonlySet<string>): ModelMessage[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{contextStorage}from"#context/container.js";import{isAuthorizationSignal,isPendingAuthorizationToolOutput,resolveActiveAuthorizationChallenges}from"#harness/authorization.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";function isInlineAuthorizationToolResult(e){return isPendingAuthorizationToolOutput(e.output)||readAuthorizationSignal(e)!==void 0}function resolveInlineAuthorizationInterrupt(e){let t=[],n=new Set;for(let
|
|
1
|
+
import{contextStorage}from"#context/container.js";import{isAuthorizationSignal,isPendingAuthorizationToolOutput,resolveActiveAuthorizationChallenges}from"#harness/authorization.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";function isInlineAuthorizationToolResult(e){return isPendingAuthorizationToolOutput(e.output)||readAuthorizationSignal(e)!==void 0}function resolveInlineAuthorizationInterrupt(e){let t=[],n=new Set,r=new Map;for(let i of e.toolResults??[]){let e=readAuthorizationSignal(i);if(e!==void 0){t.push(e),n.add(i.toolCallId);for(let t of e.challenges){let e=r.get(t.name)??[];r.set(t.name,[...e,i.toolCallId])}}}if(t.length!==0)return{callIdsByName:r,challenges:resolveActiveAuthorizationChallenges(t.flatMap(e=>e.challenges)),history:withoutCalls(e.messages,n)}}function readAuthorizationSignal(e){let t=contextStorage.getStore(),n=t===void 0?void 0:readToolInterrupt(t,e.toolCallId);return n!==void 0&&isAuthorizationSignal(n)?n:isAuthorizationSignal(e.output)?e.output:void 0}function withoutCalls(e,t){return e.flatMap(e=>{if(e.role===`assistant`&&Array.isArray(e.content)){let n=e.content.some(e=>e.type===`tool-call`&&t.has(e.toolCallId)),r=e.content.filter(e=>e.type!==`tool-call`||!t.has(e.toolCallId)),i=r.some(e=>e.type===`tool-call`);return r.length===0||n&&!i?[]:[{...e,content:r}]}if(e.role===`tool`){let n=e.content.filter(e=>e.type!==`tool-result`||!t.has(e.toolCallId));return n.length===0?[]:[{...e,content:n}]}return[e]})}export{isInlineAuthorizationToolResult,resolveInlineAuthorizationInterrupt,withoutCalls};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContentPart,
|
|
1
|
+
import type { ContentPart, ToolSet } from "ai";
|
|
2
2
|
import type { InputRequest } from "#shared/input.js";
|
|
3
3
|
/**
|
|
4
4
|
* Extracts tool approval input requests from AI SDK content parts that
|
|
@@ -8,12 +8,3 @@ export declare function extractToolApprovalInputRequests(input: {
|
|
|
8
8
|
readonly content: readonly ContentPart<ToolSet>[];
|
|
9
9
|
readonly excludedCallIds?: ReadonlySet<string>;
|
|
10
10
|
}): InputRequest[];
|
|
11
|
-
/**
|
|
12
|
-
* Recovers approval request metadata for submitted input response IDs from
|
|
13
|
-
* model history. The newest occurrence wins so compacted or repeated history
|
|
14
|
-
* does not replace the request that is closest to the current turn.
|
|
15
|
-
*/
|
|
16
|
-
export declare function extractHistoricalInputRequests(input: {
|
|
17
|
-
readonly history: readonly ModelMessage[];
|
|
18
|
-
readonly requestIds: ReadonlySet<string>;
|
|
19
|
-
}): ReadonlyMap<string, InputRequest>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{toolCallDisplayName}from"#execution/tools/connection-target.js";import{createRuntimeToolCallActionFromToolCall}from"#harness/tool-call-action.js";const ToolCallDescriptorSchema=z.object({input:z.unknown(),toolCallId:z.string(),toolName:z.string()}),PersistedToolCallSchema=ToolCallDescriptorSchema.extend({type:z.literal(`tool-call`)}),ToolApprovalRequestSchema=z.object({approvalId:z.string(),isAutomatic:z.boolean().optional().catch(void 0),toolCall:ToolCallDescriptorSchema.optional().catch(void 0),toolCallId:z.string().optional().catch(void 0),type:z.literal(`tool-approval-request`)});function extractToolApprovalInputRequests(e){return extractApprovalRequests(e)}function extractApprovalRequests(e){let t=[],n=new Map;for(let t of e.content){let e=PersistedToolCallSchema.safeParse(t);e.success&&n.set(e.data.toolCallId,e.data)}for(let r of e.content){let i=ToolApprovalRequestSchema.safeParse(r);if(!i.success)continue;let a=i.data;if(
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{toolCallDisplayName}from"#execution/tools/connection-target.js";import{createRuntimeToolCallActionFromToolCall}from"#harness/tool-call-action.js";const ToolCallDescriptorSchema=z.object({input:z.unknown(),toolCallId:z.string(),toolName:z.string()}),PersistedToolCallSchema=ToolCallDescriptorSchema.extend({type:z.literal(`tool-call`)}),ToolApprovalRequestSchema=z.object({approvalId:z.string(),isAutomatic:z.boolean().optional().catch(void 0),toolCall:ToolCallDescriptorSchema.optional().catch(void 0),toolCallId:z.string().optional().catch(void 0),type:z.literal(`tool-approval-request`)});function extractToolApprovalInputRequests(e){return extractApprovalRequests(e)}function extractApprovalRequests(e){let t=[],n=new Map;for(let t of e.content){let e=PersistedToolCallSchema.safeParse(t);e.success&&n.set(e.data.toolCallId,e.data)}for(let r of e.content){let i=ToolApprovalRequestSchema.safeParse(r);if(!i.success)continue;let a=i.data;if(a.isAutomatic===!0)continue;let o=a.toolCall??(a.toolCallId===void 0?void 0:n.get(a.toolCallId));o!==void 0&&(e.excludedCallIds?.has(o.toolCallId)||t.push({action:createRuntimeToolCallActionFromToolCall({toolCall:o}),allowFreeform:!1,display:`confirmation`,kind:`tool-approval`,options:[{id:`approve`,label:`Approve`},{id:`cancel`,label:`Cancel`}],prompt:`Approve ${toolCallDisplayName(o.toolName,o.input)}?`,requestId:a.approvalId}))}return t}export{extractToolApprovalInputRequests};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PendingInputBatchEvent } from "#harness/
|
|
1
|
+
import type { StepCoordinates as PendingInputBatchEvent } from "#harness/session-machine/view.js";
|
|
2
2
|
import type { InputRequest, InputResponse } from "#shared/input.js";
|
|
3
3
|
export declare const TOOL_EXECUTION_DENIED_MESSAGE = "Tool execution was denied.";
|
|
4
4
|
type ApprovalTerminalStatus = "approved" | "denied" | "ignored" | "invalid";
|
|
@@ -10,10 +10,6 @@ export interface ResolvedInputBatch {
|
|
|
10
10
|
readonly response?: InputResponse;
|
|
11
11
|
}[];
|
|
12
12
|
}
|
|
13
|
-
export declare function buildResolvedInputBatch(batch: {
|
|
14
|
-
readonly event?: PendingInputBatchEvent;
|
|
15
|
-
readonly requests: readonly InputRequest[];
|
|
16
|
-
}, responses: readonly InputResponse[]): ResolvedInputBatch | undefined;
|
|
17
13
|
/**
|
|
18
14
|
* One request's terminal outcome once its batch resolves: an approval's
|
|
19
15
|
* decision, or whether a question received a response.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const TOOL_EXECUTION_DENIED_MESSAGE=`Tool execution was denied.`;function
|
|
1
|
+
const TOOL_EXECUTION_DENIED_MESSAGE=`Tool execution was denied.`;function resolveInputOutcome(e,t){return e===`tool-approval`?resolveApprovalOutcome(t).status:t===void 0?`ignored`:`answered`}function resolveApprovalOutcome(e){return e===void 0?{approved:!1,reason:`Ignored because the user continued without responding.`,status:`ignored`}:e.optionId===`approve`?{approved:!0,reason:void 0,status:`approved`}:e.optionId===`cancel`||e.optionId===`deny`?{approved:!1,reason:TOOL_EXECUTION_DENIED_MESSAGE,status:`denied`}:{approved:!1,reason:`Invalid approval response.`,status:`invalid`}}export{TOOL_EXECUTION_DENIED_MESSAGE,resolveApprovalOutcome,resolveInputOutcome};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type LanguageModel, type ModelMessage } from "ai";
|
|
2
|
+
import type { GenerationSteering } from "#harness/generation-steering.js";
|
|
3
|
+
import type { HarnessModelMessage, UserModelMessage } from "#harness/messages.js";
|
|
4
|
+
import { type AnthropicCacheMarker, type PromptCachePath } from "#harness/prompt-cache.js";
|
|
5
|
+
import type { Step } from "#harness/step/context.js";
|
|
6
|
+
import { type Prompt } from "#harness/step/prompt.js";
|
|
7
|
+
import { type HarnessStepResult } from "#harness/step-hooks.js";
|
|
8
|
+
import type { StepResult } from "#harness/types.js";
|
|
9
|
+
import type { InstrumentationAttempt } from "#instrumentation/runtime.js";
|
|
10
|
+
import { type RequestMessages } from "./request.js";
|
|
11
|
+
import { type ModelTools } from "./tools.js";
|
|
12
|
+
/** How one attempt differs from the step's first: what recovery and retries change. */
|
|
13
|
+
export interface ModelCallOptions {
|
|
14
|
+
readonly disabledProviderTools?: ReadonlySet<string>;
|
|
15
|
+
readonly extraSystemNote?: string;
|
|
16
|
+
readonly retryReason?: "empty-response";
|
|
17
|
+
readonly suppressStepStartedEmission?: boolean;
|
|
18
|
+
readonly trailingUserNote?: string;
|
|
19
|
+
}
|
|
20
|
+
/** What a model step's caller needs from the step. */
|
|
21
|
+
interface ModelCallerInput {
|
|
22
|
+
readonly model: LanguageModel;
|
|
23
|
+
readonly generation: GenerationSteering;
|
|
24
|
+
readonly hidesHeldText: boolean;
|
|
25
|
+
readonly turnMessages: readonly UserModelMessage[];
|
|
26
|
+
readonly approvedTools: ReadonlySet<string>;
|
|
27
|
+
readonly pendingApprovalsNote: string | undefined;
|
|
28
|
+
/** The prompt as the step started it, projected for the model. */
|
|
29
|
+
readonly projectedMessages: HarnessModelMessage[];
|
|
30
|
+
readonly startStep: (messages: readonly ModelMessage[]) => Promise<void>;
|
|
31
|
+
readonly setAttemptScope: (scope: InstrumentationAttempt | undefined) => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Calls the model for one step. Each attempt rebuilds the tools, the request, and the agent, so an
|
|
35
|
+
* earlier stream can't resolve a retry's one-shot step hooks with stale partial output. An attempt
|
|
36
|
+
* may first compact the prompt, which rewrites the durable messages the step later commits.
|
|
37
|
+
*/
|
|
38
|
+
export declare class ModelCaller {
|
|
39
|
+
readonly cachePath: PromptCachePath;
|
|
40
|
+
readonly marker: AnthropicCacheMarker | undefined;
|
|
41
|
+
private readonly attributionHeaders;
|
|
42
|
+
/** The prompt as the model reads it, projected for its history view. */
|
|
43
|
+
private projectedMessages;
|
|
44
|
+
/** The latest attempt's request; its history is what the step commits. */
|
|
45
|
+
request: RequestMessages;
|
|
46
|
+
/** The latest attempt's tools, which decide how the step's calls defer and end the turn. */
|
|
47
|
+
tools: ModelTools | undefined;
|
|
48
|
+
/** The messages the latest attempt sent, after attachments were hydrated. */
|
|
49
|
+
modelMessages: ModelMessage[];
|
|
50
|
+
requestEnvelopeTokens: number;
|
|
51
|
+
/** Usage of a call steering interrupted, which the steered step still counts. */
|
|
52
|
+
private interruptedUsage;
|
|
53
|
+
private compactionFailure;
|
|
54
|
+
private attemptIndex;
|
|
55
|
+
private readonly step;
|
|
56
|
+
private readonly prompt;
|
|
57
|
+
private readonly input;
|
|
58
|
+
constructor(step: Step, prompt: Prompt, input: ModelCallerInput);
|
|
59
|
+
/** Calls the model, retrying transient failures. */
|
|
60
|
+
call(options: ModelCallOptions): Promise<HarnessStepResult>;
|
|
61
|
+
/** A failed compaction fails the step, whatever recovery the call attempted. */
|
|
62
|
+
throwIfCompactionFailed(): void;
|
|
63
|
+
/** Steering interrupted the call: the step ends with what it committed, and runs again. */
|
|
64
|
+
steered(): Promise<StepResult>;
|
|
65
|
+
/** The step's result counted its usage, so an interrupted call's usage no longer applies. */
|
|
66
|
+
clearInterruptedUsage(): void;
|
|
67
|
+
private buildRequest;
|
|
68
|
+
private instructions;
|
|
69
|
+
private prepare;
|
|
70
|
+
/** Compacts the prompt when it's over the threshold, then rebuilds what depends on it. */
|
|
71
|
+
private compact;
|
|
72
|
+
private attempt;
|
|
73
|
+
/** Streams the call, publishing its content as it arrives. */
|
|
74
|
+
private stream;
|
|
75
|
+
/** Runs the call without a listener: nothing streams. */
|
|
76
|
+
private generate;
|
|
77
|
+
}
|
|
78
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{buildGatewayAttributionHeaders}from"./model.js";import{isEmptyModelResponse,rethrowNoOutputAsEmptyResponse}from"./recovery.js";import{modelInstructions,requestMessages,withTrailingUserNote}from"./request.js";import{answerSkippedToolCalls,appendMissingToolResultMessages,extractToolResultCallIds,withAccumulatedResponseMessages}from"./response.js";import{runModelCallWithRetries}from"./retry.js";import{logToolExecutionError,prepareModelTools}from"./tools.js";import{extractGatewayCostUsd,extractTokenUsageDelta}from"./usage.js";import{ToolLoopAgent,isStepCount}from"ai";import{createLogger,logError}from"#internal/logging.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{createStepCompletedEvent}from"#protocol/message.js";import{activeTurnId}from"#harness/session-machine/view.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{hydrateSandboxAttachments,moveToolResultFilesToUserMessages}from"#harness/attachment-staging.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{summarizeKnownError}from"#harness/semantic-errors/index.js";import{estimateTokens}from"#harness/token-estimate.js";import{estimateRequestEnvelope}from"#harness/request-envelope.js";import{workingTaskIds}from"#execution/tasks/model-step.js";import{ContentFilteredModelResponseError,EmptyModelResponseError}from"#harness/model-call/errors.js";import{interruptStreamOnFailure}from"#harness/interruptible-stream.js";import{buildToolApproval}from"#harness/tools.js";import{compactPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";import{emitStreamContent}from"#harness/emission.js";import{FINAL_OUTPUT_TOOL_NAME}from"#harness/final-output.js";import{detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{buildStepHooks,emitStepActions,readGatewayGenerationId}from"#harness/step-hooks.js";import{maybeCompact}from"#harness/compaction/step.js";const environment=process.env.NODE_ENV??`unknown`,log=createLogger(`harness.tool-loop`);var ModelCaller=class{cachePath;marker;attributionHeaders;projectedMessages;request;tools;modelMessages=[];requestEnvelopeTokens=0;interruptedUsage;compactionFailure;attemptIndex=0;step;prompt;input;constructor(e,t,n){this.step=e,this.prompt=t,this.input=n,this.cachePath=detectPromptCachePath(n.model),this.marker=this.cachePath.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,this.attributionHeaders=buildGatewayAttributionHeaders(n.model,e.config.runtimeIdentity),this.projectedMessages=n.projectedMessages,this.request=this.buildRequest(e.config.tools)}async call(e){return await runModelCallWithRetries(t=>this.attempt({...e,suppressStepStartedEmission:t!==1||e.suppressStepStartedEmission}),{canRetry:()=>this.compactionFailure===void 0,sessionId:this.step.session.sessionId,turnId:this.step.position().turnId},this.input.generation.signal)}throwIfCompactionFailed(){if(this.compactionFailure!==void 0)throw this.compactionFailure.error}async steered(){let{step:e}=this;return throwIfTurnAborted(e.config.abortSignal),e.ctx?.set(HistoryStateKey,this.request.historyState),this.interruptedUsage!==void 0&&(e.session=setTurnUsageState(e.session,accumulateTurnUsage({previous:getTurnUsageState(e.session.state),turnId:e.position().turnId,usage:this.interruptedUsage}))),await e.emit?.(createStepCompletedEvent({...e.position(),finishReason:`other`,usage:this.interruptedUsage})),{next:e.runStep,session:{...e.session,history:[...this.request.history]},steered:!0}}clearInterruptedUsage(){this.interruptedUsage=void 0}buildRequest(e){return requestMessages(this.step,{coordinationTools:e,hidesHeldText:this.input.hidesHeldText,messages:this.prompt.messages,pendingApprovalsNote:this.input.pendingApprovalsNote,projectedMessages:this.projectedMessages,turnMessages:this.input.turnMessages})}instructions(e){return modelInstructions({extraSystemNote:e,marker:this.marker,session:this.step.session,systemMessages:this.request.systemMessages})}async prepare(e){let t=await prepareModelTools(this.step,{model:this.input.model,approvedTools:this.input.approvedTools,disabledProviderTools:e.disabledProviderTools,generation:this.input.generation,marker:this.marker});return this.tools=t,this.request=this.buildRequest(t.coordinationTools),this.requestEnvelopeTokens=await estimateRequestEnvelope({history:this.projectedMessages,instructions:this.instructions(e.extraSystemNote),messages:withTrailingUserNote(this.request.nonSystemMessages,e.trailingUserNote),tools:t.effectiveTools}),t}async compact(e,t){let{step:n,prompt:r}=this,{config:i}=n,a;try{a=await maybeCompact({abortSignal:i.abortSignal,auth:n.ctx?.get(AuthKey)??null,emissionState:n.position(),historyProjector:i.historyProjector,messages:[...r.messages],model:this.input.model,promptMessages:withClientContext(r),publish:n.publish,requestEnvelopeTokens:this.requestEnvelopeTokens,resolveModel:i.resolveModel,runtimeIdentity:i.runtimeIdentity,session:n.session,telemetry:n.instrumentation?.telemetry()})}catch(e){throw this.compactionFailure={error:e},e}if(n.session=a.session,!a.compacted)return t;compactPrompt(n,r,a.messages);let{compaction:o}=n.session;return n.session={...n.session,compaction:{recentWindowSize:o.recentWindowSize,threshold:o.threshold,thresholdPercent:o.thresholdPercent}},this.projectedMessages=projectPrompt(n,r),await this.prepare(e)}async attempt(e){let{step:t}=this,{generation:n,model:r}=this.input,i=await this.compact(e,await this.prepare(e));this.requestEnvelopeTokens=Math.max(0,this.requestEnvelopeTokens-(estimateTokens(this.request.history)-estimateTokens(this.prompt.messages))),n.begin(),this.modelMessages=await hydrateSandboxAttachments(this.request.nonSystemMessages),typeof this.input.model!=`string`&&typeof this.input.model.provider==`string`&&this.input.model.provider.endsWith(`.chat`)&&(this.modelMessages=moveToolResultFilesToUserMessages(this.modelMessages));let a=this.instructions(e.extraSystemNote),o=t.instrumentation?.resolveRuntimeContext({emissionState:t.position(),environment,modelInput:{instructions:a,messages:this.modelMessages},session:t.session})??{};e.retryReason&&(o[`eve.retry.reason`]=e.retryReason);let s=withTrailingUserNote(this.modelMessages,e.trailingUserNote),c=t.position(),l=t.instrumentation?.prepareAttempt({isFrameworkTool:e=>t.frameworkToolNames.has(e),attemptIndex:this.attemptIndex++,runtimeContext:o,stepIndex:c.stepIndex,turnId:activeTurnId(c)});this.input.setAttemptScope(l?.scope);let u=buildStepHooks({auth:t.ctx?.get(AuthKey)??null,cachePath:this.cachePath,marker:this.marker,session:t.session,startStep:e.suppressStepStartedEmission===!0?void 0:this.input.startStep}),d={headers:this.attributionHeaders,instructions:a,model:r,onLanguageModelCallEnd:e=>{n.interrupted||(this.interruptedUsage=extractTokenUsageDelta({costUsd:extractGatewayCostUsd(e.providerMetadata),usage:e.usage}))},onToolExecutionEnd:logToolExecutionError,onError(e){n.interrupted||summarizeKnownError(e.error)?.tags.includes(`config`)!==!0&&logError(log,`tool-loop stream error`,e.error)},onStepEnd:u.onStepEnd,onStepStart:u.onStepStart,prepareStep:u.prepareStep,reasoning:t.session.agent.modelReference?.reasoning??t.session.agent.reasoning,runtimeContext:o,stopWhen:isStepCount(1),telemetry:l?.telemetry,toolApproval:buildToolApproval(i.modelTools,n.signal),tools:i.effectiveTools},f=new ToolLoopAgent(d);try{let e=t.emit===void 0?await this.generate(f,s,u.stepResult):await this.stream(f,s,u.stepResult,i);return await l?.complete(),e}catch(e){return n.interrupted?await l?.complete():await l?.fail(e),n.check(),rethrowNoOutputAsEmptyResponse(e)}}async stream(e,t,n,r){let{step:i}=this,{generation:a}=this.input,o=new Set([FINAL_OUTPUT_TOOL_NAME]),s=await e.stream({abortSignal:a.signal,messages:t}),{emittedActionCallIds:c,handledInlineToolResultCallIds:l,invalidInputToolCallIds:u,inlineAuthorizationResults:d,trailingInlineToolResultParts:f}=await emitStreamContent(i.publish,i.position(),interruptStreamOnFailure(s.fullStream,a.signal),{excludedActionToolNames:o,hidesHeldText:this.input.hidesHeldText&&workingTaskIds(i.session).length>0,tools:r.presentationTools});throwIfTurnAborted(i.config.abortSignal),a.check();let[p,m]=await Promise.all([n,s.responseMessages]);assertUsableResponse(p,m,d.length>0||f.length>0);let h=answerSkippedToolCalls(p,r.effectiveTools);await emitStepActions(i.publish,i.position(),h.length===0?p:withAccumulatedResponseMessages({stepResult:p,responseMessages:appendMissingToolResultMessages({append:h,responseMessages:p.response.messages})}),{emittedActionCallIds:c,excludedActionCallIds:u,excludedActionToolNames:o,handledInlineToolResultCallIds:l,tools:r.presentationTools});let g=new Map(p.toolResults.map(e=>[e.toolCallId,e]));for(let e of d)g.set(e.toolCallId,e);return withAccumulatedResponseMessages({invalidInputToolCallIds:u,responseMessages:appendMissingToolResultMessages({append:[...f,...answerSkippedToolCalls(p,r.effectiveTools)],responseMessages:m}),stepResult:p,toolResults:[...g.values()]})}async generate(e,t,n){let{generation:r}=this.input,i=await e.generate({abortSignal:r.signal,messages:t});throwIfTurnAborted(this.step.config.abortSignal),r.check();let a=await n;return assertUsableResponse(a,i.responseMessages,!1),withAccumulatedResponseMessages({responseMessages:appendMissingToolResultMessages({append:answerSkippedToolCalls(a,this.tools.effectiveTools),responseMessages:i.responseMessages}),stepResult:a})}};function assertUsableResponse(e,t,n){if(e.finishReason===`content-filter`)throw new ContentFilteredModelResponseError(readGatewayGenerationId(e.providerMetadata));if(isEmptyModelResponse(e)&&extractToolResultCallIds(t).size===0&&!n)throw new EmptyModelResponseError}export{ModelCaller};
|
|
@@ -41,7 +41,7 @@ export declare function extractUnsupportedProviderToolTypes(error: unknown): rea
|
|
|
41
41
|
*/
|
|
42
42
|
export declare function extractModelCallErrorDetails(error: unknown): JsonObject;
|
|
43
43
|
/**
|
|
44
|
-
* A model call that produced no content. Raised by
|
|
44
|
+
* A model call that produced no content. Raised by the model caller from
|
|
45
45
|
* either of its two triggers: `isEmptyModelResponse` (a completed step
|
|
46
46
|
* with finishReason 'other' and no output — AI Gateway HTTP 200 whose
|
|
47
47
|
* stream carries no content, no usage, and no error) or
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { JsonObject } from "#shared/json.js";
|
|
2
|
+
import type { SemanticErrorSummary } from "#harness/semantic-errors/rule.js";
|
|
3
|
+
import { type UpstreamRejectionSummary } from "#harness/model-call/errors.js";
|
|
4
|
+
import type { Step } from "#harness/step/context.js";
|
|
5
|
+
import type { StepResult } from "#harness/types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Projects a model-call failure into the `step.failed` / `turn.failed`
|
|
8
|
+
* `details` payload. Three mutually exclusive branches:
|
|
9
|
+
*
|
|
10
|
+
* 1. Catalog match → the rule's curated `name`/`message`/`hint` plus its
|
|
11
|
+
* registered `semanticErrorId`, no SDK inspector dump.
|
|
12
|
+
* 2. Upstream rejection → raw error `message` with the extracted upstream
|
|
13
|
+
* identity, no inspector dump. No `semanticErrorId`: the message is
|
|
14
|
+
* arbitrary provider prose, not a registered failure shape.
|
|
15
|
+
* 3. Fallback → full {@link formatError} projection (cause chain via
|
|
16
|
+
* `util.inspect`) so unrecognized failures still carry the upstream
|
|
17
|
+
* stack to log aggregators.
|
|
18
|
+
*
|
|
19
|
+
* All branches merge {@link extractModelCallErrorDetails} on top so the
|
|
20
|
+
* compact gateway diagnostics (`statusCode`, `upstreamMessage`,
|
|
21
|
+
* `responseBodySnippet`, ...) always show up next to the message.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildModelCallFailureDetails(input: {
|
|
24
|
+
readonly catalogSummary: SemanticErrorSummary | null;
|
|
25
|
+
readonly error: unknown;
|
|
26
|
+
readonly errorId: string;
|
|
27
|
+
readonly modelCallDetails: JsonObject;
|
|
28
|
+
readonly upstreamRejection: UpstreamRejectionSummary | null;
|
|
29
|
+
}): JsonObject;
|
|
30
|
+
/**
|
|
31
|
+
* Builds the structured log fields for a model-call failure. When the
|
|
32
|
+
* failure was recognized (catalog match or extracted upstream rejection),
|
|
33
|
+
* attach the compact `details` payload and *omit* the raw `error` so the
|
|
34
|
+
* logger's `util.inspect` of the cause chain (which would render
|
|
35
|
+
* `[object Object]` for upstream `APICallError` shapes) is bypassed.
|
|
36
|
+
* Otherwise fall back to the raw error so unrecognized failures keep
|
|
37
|
+
* their full stack in logs.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildModelCallFailureLogFields(input: {
|
|
40
|
+
readonly error: unknown;
|
|
41
|
+
readonly errorId: string;
|
|
42
|
+
readonly modelCallDetails: JsonObject;
|
|
43
|
+
readonly recognized: boolean;
|
|
44
|
+
readonly sessionId: string;
|
|
45
|
+
readonly turnId: string;
|
|
46
|
+
}): Record<string, unknown>;
|
|
47
|
+
/**
|
|
48
|
+
* The model call failed past its retries and recoveries. A failed write to the session's stream is
|
|
49
|
+
* the workflow's failure, not the model's: the session parks for the user to retry. A terminal
|
|
50
|
+
* failure ends the session; any other fails the turn recoverably.
|
|
51
|
+
*/
|
|
52
|
+
export declare function reportModelCallFailure(step: Step, error: unknown): Promise<StepResult>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createErrorId,createLogger,formatError}from"#internal/logging.js";import{toErrorMessage}from"#shared/errors.js";import{fail}from"#harness/session-machine/transitions.js";import{summarizeKnownError}from"#harness/semantic-errors/index.js";import{classifyModelCallError,extractModelCallErrorDetails,extractUpstreamRejectionMessage}from"#harness/model-call/errors.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";const log=createLogger(`harness.tool-loop`);function buildModelCallFailureDetails(e){let{catalogSummary:t,error:n,errorId:r,modelCallDetails:i,upstreamRejection:a}=e;if(t!==null){let e={errorId:r,message:t.message,name:t.name,semanticErrorId:t.id,...i};return t.hint!==void 0&&(e.hint=t.hint),e}return a===null?{...formatError(n,r),...i}:{errorId:r,message:toErrorMessage(n),name:a.name,...i}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.recognized?{...t,details:e.modelCallDetails}:{...t,error:e.error}}async function reportModelCallFailure(e,t){if(e.instrumentation?.recordError(t),e.emit===void 0)throw t;let{sessionId:n}=e.session,{turnId:r}=e.position(),i=extractWorkflowStreamWriteErrorDetails(t);if(i!==null){let a=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...i,errorId:a,error:t,sessionId:n,turnId:r}),await e.apply(fail(e.view(),{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...i,errorId:a},message:toErrorMessage(t)})),{next:null,session:e.session}}let a=createErrorId(),o=summarizeKnownError(t),s=o===null?extractUpstreamRejectionMessage(t):null,c=o?.message??s?.message??toErrorMessage(t),l=o?.hint===void 0?c:`${c} ${o.hint}`,u=extractModelCallErrorDetails(t),d=buildModelCallFailureDetails({catalogSummary:o,error:t,errorId:a,modelCallDetails:u,upstreamRejection:s}),f=buildModelCallFailureLogFields({error:t,errorId:a,modelCallDetails:u,recognized:o!==null||s!==null,sessionId:n,turnId:r});return classifyModelCallError(t)===`terminal`?(o===null?log.error(s?.message??`model call failed terminally`,f):log.error(`${o.name}: ${o.message}`,{errorId:a,hint:o.hint,sessionId:n,turnId:r}),await e.apply(fail(e.view(),{code:`MODEL_CALL_FAILED`,details:d,message:c,terminal:{sessionId:n}})),{next:e.hasDelegatedCaller?{done:!0,isError:!0,output:l}:{done:!0,output:``},session:e.session}):(log.error(s?.message??`model call failed — parking session for retry by the user`,f),await e.apply(fail(e.view(),{code:`MODEL_CALL_FAILED`,details:d,message:c})),e.session={...e.session,outputSchema:void 0},{next:null,session:e.session,settledTurn:{isError:!0,output:l}})}export{buildModelCallFailureDetails,buildModelCallFailureLogFields,reportModelCallFailure};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LanguageModel } from "ai";
|
|
2
|
+
import type { HarnessSession, ToolLoopHarnessConfig } from "#harness/types.js";
|
|
3
|
+
import { contextStorage } from "#context/container.js";
|
|
4
|
+
/**
|
|
5
|
+
* Builds AI Gateway app attribution headers when the model is gateway-routed.
|
|
6
|
+
*
|
|
7
|
+
* Bare model ids and `gateway.*` model instances route through AI Gateway.
|
|
8
|
+
* Direct-provider model instances receive no Gateway-specific headers.
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildGatewayAttributionHeaders(model: LanguageModel, runtimeIdentity: ToolLoopHarnessConfig["runtimeIdentity"]): Record<string, string> | undefined;
|
|
11
|
+
export declare function resolveEffectiveRuntimeModel(input: {
|
|
12
|
+
readonly config: ToolLoopHarnessConfig;
|
|
13
|
+
readonly ctx: ReturnType<typeof contextStorage.getStore>;
|
|
14
|
+
readonly session: HarnessSession;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
readonly model: LanguageModel;
|
|
17
|
+
readonly session: HarnessSession;
|
|
18
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"#context/container.js";import{resolveProviderHeaders}from"#internal/gateway.js";import{getEffectiveModelSelection}from"#context/effective-model.js";function buildGatewayAttributionHeaders(e,t){let n=resolveProviderHeaders(e);if(n===void 0)return;let r=t?.agentName??t?.agentId,i=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,a=i?`https://${i}`:void 0,o={...n};return r&&(o[`x-title`]=r),a&&(o[`http-referer`]=a),o}async function resolveEffectiveRuntimeModel(e){if(e.ctx===void 0){let t=e.session.agent.modelReference;if(t===void 0)throw Error(`Dynamic model selection is unavailable outside an eve runtime context.`);return{model:await e.config.resolveModel(t),session:e.session}}let t=getEffectiveModelSelection(e.ctx);if(t===null)throw Error(`Dynamic model selection is required before model-dependent work begins. Add a matching resolver handler that returns a concrete model.`);return{model:t.model===void 0?await e.config.resolveModel(t.reference):t.model,session:updateSessionModelReference(e.session,t.reference)}}function updateSessionModelReference(e,t){return e.agent.modelReference===t?e:{...e,agent:{...e.agent,modelReference:t},compaction:updateCompactionThresholdForModelReference({compaction:e.compaction,modelReference:t})}}function updateCompactionThresholdForModelReference(e){return e.modelReference.contextWindowTokens===void 0?e.compaction:{...e.compaction,threshold:Math.max(1,Math.floor(e.modelReference.contextWindowTokens*(e.compaction.thresholdPercent??.9)))}}export{buildGatewayAttributionHeaders,resolveEffectiveRuntimeModel};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { HarnessStepResult } from "#harness/step-hooks.js";
|
|
2
|
+
/** How a recovery reissues the call. */
|
|
3
|
+
type RecoveryCall = (options: {
|
|
4
|
+
readonly disabledProviderTools?: ReadonlySet<string>;
|
|
5
|
+
readonly extraSystemNote?: string;
|
|
6
|
+
readonly retryReason?: "empty-response";
|
|
7
|
+
readonly suppressStepStartedEmission?: boolean;
|
|
8
|
+
readonly trailingUserNote?: string;
|
|
9
|
+
}) => Promise<HarnessStepResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Recovers a failed model call, each recovery at most once and within the current step, so the
|
|
12
|
+
* reissue suppresses a second `step.started`:
|
|
13
|
+
*
|
|
14
|
+
* 1. AI Gateway rejected a provider-specific tool a fallback provider can't serve ("tool type 'X'
|
|
15
|
+
* is not supported"): the call is reissued without it, and a system note tells the model which
|
|
16
|
+
* capability went away. Only known provider tools are dropped, never an authored one.
|
|
17
|
+
* 2. The response was empty (see {@link EmptyModelResponseError}), including the first
|
|
18
|
+
* recovery's: the call is reissued with {@link EMPTY_RESPONSE_NUDGE}, repeating what the first
|
|
19
|
+
* recovery removed.
|
|
20
|
+
*
|
|
21
|
+
* Each reissue goes through `call` so it gets fresh step hooks: the failed attempt's one-shot
|
|
22
|
+
* `stepResult` already resolved. Returns the error that remains when nothing recovered.
|
|
23
|
+
*/
|
|
24
|
+
export declare function recoverModelCall(input: {
|
|
25
|
+
readonly error: unknown;
|
|
26
|
+
readonly call: RecoveryCall;
|
|
27
|
+
readonly sessionId: string;
|
|
28
|
+
readonly turnId: string;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
readonly result: HarnessStepResult;
|
|
31
|
+
} | {
|
|
32
|
+
readonly error: unknown;
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* True when a step produced no assistant text and no tool calls. A blank
|
|
36
|
+
* response is ambiguous and must be retried instead of silently dropping a
|
|
37
|
+
* HITL reply.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isEmptyModelResponse(step: HarnessStepResult): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Rethrows the AI SDK's `NoOutputGeneratedError` as
|
|
42
|
+
* {@link EmptyModelResponseError}. Since `ai@7.0.0-canary.169`
|
|
43
|
+
* (vercel/ai#15938) a stream that closes after metadata without output or
|
|
44
|
+
* a finish chunk rejects — the SDK enqueues the error onto `fullStream`
|
|
45
|
+
* (so `emitStreamContent` throws it) and never emits `finish-step`, so
|
|
46
|
+
* `onStepEnd` does not fire and the step hooks' `stepResult` promise
|
|
47
|
+
* would never settle. The same condition previously completed as an empty
|
|
48
|
+
* step caught by {@link isEmptyModelResponse}; normalizing here funnels
|
|
49
|
+
* both shapes into the one-shot empty-response reissue.
|
|
50
|
+
*/
|
|
51
|
+
export declare function rethrowNoOutputAsEmptyResponse(error: unknown): never;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{resolveAssistantStepText}from"#harness/messages.js";import{EmptyModelResponseError,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError}from"#harness/model-call/errors.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";const log=createLogger(`harness.tool-loop`);async function recoverModelCall(e){let{error:t}=e,n={sessionId:e.sessionId,turnId:e.turnId},r={},i=extractUnsupportedProviderToolTypes(t),a=[...new Set(i.flatMap(e=>resolveFrameworkToolFromUpstreamType(e)??[]))];if(a.length>0){log.warn(`disabling unsupported provider tool(s); retrying step once`,{...n,disabled:a,upstreamTypes:i}),r={disabledProviderTools:new Set(a),extraSystemNote:buildDisabledToolNote(a)};try{return{result:await e.call({...r,suppressStepStartedEmission:!0})}}catch(e){t=e}}if(t instanceof EmptyModelResponseError){log.warn(`empty model response; reissuing the model call once`,n);try{return{result:await e.call({...r,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:EMPTY_RESPONSE_NUDGE})}}catch(e){t=e}}return{error:t}}function buildDisabledToolNote(e){let t=e.join(`, `);return`The following ${e.length===1?`tool is`:`tools are`} not available with the current model and has been removed: ${t}. Proceed using the remaining tools or your training knowledge.`}function isEmptyModelResponse(e){return e.toolCalls.length===0&&e.toolResults.length===0&&resolveAssistantStepText(e.response.messages,e.text)===null}function rethrowNoOutputAsEmptyResponse(e){throw isNoOutputGeneratedError(e)?new EmptyModelResponseError({cause:e}):e}const EMPTY_RESPONSE_NUDGE=`Your previous reply was empty and was not delivered. Continue the current user request. Reuse completed results when they satisfy the request. If existing results are stale or insufficient, use the appropriate read tools to get fresh results. Do not repeat writes or other side effects that already completed. Do not mention this notice.`;export{isEmptyModelResponse,recoverModelCall,rethrowNoOutputAsEmptyResponse};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ModelMessage, SystemModelMessage } from "ai";
|
|
2
|
+
import { createCurrentMessages } from "#harness/current-messages.js";
|
|
3
|
+
import { type HarnessModelMessage, type UserModelMessage } from "#harness/messages.js";
|
|
4
|
+
import { type AnthropicCacheMarker } from "#harness/prompt-cache.js";
|
|
5
|
+
import type { Step } from "#harness/step/context.js";
|
|
6
|
+
import type { HarnessSession, HarnessToolMap } from "#harness/types.js";
|
|
7
|
+
export type RequestMessages = ReturnType<typeof createCurrentMessages>;
|
|
8
|
+
/**
|
|
9
|
+
* The messages one model call sends: the durable prompt, then the step's system instructions and
|
|
10
|
+
* announcements. Announcements persist ahead of the new input, or after earlier tool results on a
|
|
11
|
+
* continuation, so later requests keep the full prefix.
|
|
12
|
+
*/
|
|
13
|
+
export declare function requestMessages(step: Step, input: {
|
|
14
|
+
readonly messages: readonly HarnessModelMessage[];
|
|
15
|
+
readonly projectedMessages: readonly HarnessModelMessage[];
|
|
16
|
+
readonly turnMessages: readonly UserModelMessage[];
|
|
17
|
+
readonly coordinationTools: HarnessToolMap;
|
|
18
|
+
readonly hidesHeldText: boolean;
|
|
19
|
+
readonly pendingApprovalsNote: string | undefined;
|
|
20
|
+
}): RequestMessages;
|
|
21
|
+
/** The call's system instructions: a retry's note, the agent's system prompt, then the step's. */
|
|
22
|
+
export declare function modelInstructions(input: {
|
|
23
|
+
readonly session: HarnessSession;
|
|
24
|
+
readonly systemMessages: readonly SystemModelMessage[];
|
|
25
|
+
readonly marker: AnthropicCacheMarker | undefined;
|
|
26
|
+
readonly extraSystemNote?: string;
|
|
27
|
+
}): SystemModelMessage | string | undefined;
|
|
28
|
+
/** A retry's note, trailing the call's messages. */
|
|
29
|
+
export declare function withTrailingUserNote(messages: readonly ModelMessage[], note?: string): ModelMessage[];
|
|
30
|
+
export declare function mergeSystemInstructions(instructions: readonly SystemModelMessage[]): SystemModelMessage | undefined;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{HistoryStateKey}from"#context/keys.js";import{createFrameworkUserMessage}from"#harness/messages.js";import{getPendingAnnouncements}from"#harness/announcements.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{taskSystemMessages}from"#execution/tasks/model-step.js";import{applySystemCacheBreakpoint}from"#harness/prompt-cache.js";import{createCurrentMessages}from"#harness/current-messages.js";function requestMessages(e,t){let{ctx:n}=e,r=createCurrentMessages(t.messages,{historyState:n?.get(HistoryStateKey),currentTurnMessages:t.turnMessages,projectedMessages:t.projectedMessages});return n!==void 0&&r.addSystem(buildDynamicInstructionMessages(n)),r.addSystem(taskSystemMessages(t.coordinationTools,{finalReplyOnly:t.hidesHeldText})),r.addAnnouncements({availableSkills:n?.get(PendingSkillAnnouncementKey),keyed:getPendingAnnouncements(n)}),t.pendingApprovalsNote!==void 0&&r.add(t.pendingApprovalsNote,`context.state`,{cacheFriendly:!1}),r}function modelInstructions(e){let{session:t}=e,n=e.extraSystemNote?[{role:`system`,content:e.extraSystemNote}]:[];if(e.systemMessages.length===0&&n.length===0)return t.agent.system??void 0;let r=t.agent.system?[{role:`system`,content:t.agent.system}]:[],i=[...n,...r,...e.systemMessages];return mergeSystemInstructions(e.marker?applySystemCacheBreakpoint(i,e.marker):i)}function withTrailingUserNote(e,t){return t?[...e,createFrameworkUserMessage(`execution.retry`,t)]:[...e]}function mergeSystemInstructions(e){if(e.length===0)return;if(e.length===1)return{...e[0]};let t;for(let n of e)n.providerOptions!==void 0&&(t={...t,...n.providerOptions});let n={role:`system`,content:e.map(e=>e.content).join(`
|
|
2
|
+
|
|
3
|
+
`)};return t!==void 0&&(n.providerOptions=t),n}export{mergeSystemInstructions,modelInstructions,requestMessages,withTrailingUserNote};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ModelMessage, ToolSet, TypedToolResult } from "ai";
|
|
2
|
+
import type { HarnessStepResult } from "#harness/step-hooks.js";
|
|
3
|
+
type StepResponseMessage = HarnessStepResult["response"]["messages"][number];
|
|
4
|
+
type ToolResponsePart = Extract<ModelMessage, {
|
|
5
|
+
role: "tool";
|
|
6
|
+
}>["content"][number];
|
|
7
|
+
type ToolResultPart = Extract<ToolResponsePart, {
|
|
8
|
+
type: "tool-result";
|
|
9
|
+
}>;
|
|
10
|
+
export declare function withAccumulatedResponseMessages(input: {
|
|
11
|
+
readonly invalidInputToolCallIds?: ReadonlySet<string>;
|
|
12
|
+
readonly responseMessages: readonly StepResponseMessage[];
|
|
13
|
+
readonly stepResult: HarnessStepResult;
|
|
14
|
+
readonly toolResults?: readonly TypedToolResult<ToolSet>[];
|
|
15
|
+
}): HarnessStepResult;
|
|
16
|
+
/** True when provider history still owes a result for any assistant tool call. */
|
|
17
|
+
export declare function hasUnansweredToolCall(messages: readonly ModelMessage[]): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Appends synthesized tool results for calls that have no result anywhere in
|
|
20
|
+
* the step's response messages. Exported for its dedupe contract: a call
|
|
21
|
+
* already answered — including provider-executed results the SDK keeps
|
|
22
|
+
* inline in the assistant message — must never receive a second
|
|
23
|
+
* `tool-result`, or the next Anthropic call rejects the history with
|
|
24
|
+
* "each tool_use must have a single result".
|
|
25
|
+
*/
|
|
26
|
+
export declare function appendMissingToolResultMessages(input: {
|
|
27
|
+
readonly append: readonly ToolResultPart[];
|
|
28
|
+
readonly responseMessages: readonly StepResponseMessage[];
|
|
29
|
+
}): StepResponseMessage[];
|
|
30
|
+
/**
|
|
31
|
+
* CallIds answered anywhere in the response messages. Scans every message
|
|
32
|
+
* role: provider-executed tool results arrive inline in the *assistant*
|
|
33
|
+
* message (the SDK only moves them to a `tool` message during provider
|
|
34
|
+
* history normalization, which runs after the backfill paths), so a
|
|
35
|
+
* tool-message-only scan would let a synthesized result duplicate them.
|
|
36
|
+
*/
|
|
37
|
+
export declare function extractToolResultCallIds(messages: readonly ModelMessage[]): ReadonlySet<string>;
|
|
38
|
+
export declare function answerSkippedToolCalls(step: HarnessStepResult, tools: ToolSet): ToolResultPart[];
|
|
39
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getInvalidToolCallInputError,isInvalidToolCall}from"#harness/tool-call-input-errors.js";function withAccumulatedResponseMessages(e){let{stepResult:t}=e;return{content:t.content,finishReason:t.finishReason,...e.invalidInputToolCallIds===void 0?{}:{invalidInputToolCallIds:e.invalidInputToolCallIds},providerMetadata:t.providerMetadata,response:{...t.response,messages:[...e.responseMessages]},text:t.text,toolCalls:t.toolCalls,toolResults:e.toolResults===void 0?t.toolResults:[...e.toolResults],usage:t.usage}}function hasUnansweredToolCall(e){let t=new Set,n=new Set;for(let r of e)if(Array.isArray(r.content))for(let e of r.content)typeof e==`object`&&e&&(e.type===`tool-call`&&t.add(e.toolCallId),e.type===`tool-result`&&n.add(e.toolCallId));for(let e of t)if(!n.has(e))return!0;return!1}function appendMissingToolResultMessages(e){let t=extractToolResultCallIds(e.responseMessages),n=e.append.filter(e=>!t.has(e.toolCallId));return[...e.responseMessages,...n.length>0?[{role:`tool`,content:[...n]}]:[]]}function extractToolResultCallIds(e){let t=new Set;for(let n of e)if(Array.isArray(n.content))for(let e of n.content)typeof e==`object`&&e&&e.type===`tool-result`&&t.add(e.toolCallId);return t}function answerSkippedToolCalls(e,t){let{finishReason:n}=e;if(n===`stop`||n===`tool-calls`)return[];let r=extractToolResultCallIds(e.response.messages),i=new Set((e.content??[]).flatMap(e=>e.type===`tool-approval-request`&&e.isAutomatic!==!0?[e.toolCall.toolCallId]:[])),a=`The tool did not run because the model response ended early (finish reason: ${n}). Call the tool again if you still need its result.`;return(e.toolCalls??[]).filter(e=>t[e.toolName]?.execute!==void 0&&e.providerExecuted!==!0&&!isInvalidToolCall(e)&&getInvalidToolCallInputError({toolCall:e})===void 0&&!r.has(e.toolCallId)&&!i.has(e.toolCallId)).map(e=>({output:{type:`error-text`,value:a},toolCallId:e.toolCallId,toolName:e.toolName,type:`tool-result`}))}export{answerSkippedToolCalls,appendMissingToolResultMessages,extractToolResultCallIds,hasUnansweredToolCall,withAccumulatedResponseMessages};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retries `fn` with exponential backoff while the thrown error is
|
|
3
|
+
* classified as `"retry"`. Rethrows the last error once attempts are
|
|
4
|
+
* exhausted or the error is classified as something other than
|
|
5
|
+
* transient.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runModelCallWithRetries<T>(fn: (attempt: number) => Promise<T>, diag: {
|
|
8
|
+
readonly sessionId: string;
|
|
9
|
+
readonly turnId: string;
|
|
10
|
+
readonly canRetry?: () => boolean;
|
|
11
|
+
}, signal: AbortSignal): Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{setTimeout}from"node:timers/promises";import{classifyModelCallError}from"#harness/model-call/errors.js";const log=createLogger(`harness.tool-loop`);async function runModelCallWithRetries(e,t,n){for(let r=1;;r++){n.throwIfAborted();try{return await e(r)}catch(e){if(n.throwIfAborted(),t.canRetry?.()===!1||r===3||classifyModelCallError(e)!==`retry`)throw e;let i=500*2**(r-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:r,delayMs:i,sessionId:t.sessionId,turnId:t.turnId,error:e}),await setTimeout(i,void 0,{signal:n})}}}export{runModelCallWithRetries};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { GenerationSteering } from "#harness/generation-steering.js";
|
|
2
|
+
import { type HarnessModelMessage } from "#harness/messages.js";
|
|
3
|
+
import { type ApprovedWork } from "#harness/hitl/index.js";
|
|
4
|
+
import { type Step } from "#harness/step/context.js";
|
|
5
|
+
import type { TurnInput } from "#harness/step/intake.js";
|
|
6
|
+
import type { HarnessStepResult } from "#harness/step-hooks.js";
|
|
7
|
+
import { type HarnessToolMap, type StepResult } from "#harness/types.js";
|
|
8
|
+
import type { InstrumentationAttempt } from "#instrumentation/runtime.js";
|
|
9
|
+
import type { EndsTurnTools } from "./tools.js";
|
|
10
|
+
/** A model step's response, for the session to act on. */
|
|
11
|
+
export interface ModelResponse {
|
|
12
|
+
readonly coordinationTools: HarnessToolMap;
|
|
13
|
+
/** How many prompt messages the model read, when no client context was spliced in. */
|
|
14
|
+
readonly durableModelPromptMessageCount?: number;
|
|
15
|
+
/** Tools that can end the turn in this step, with their `endsTurn` option. */
|
|
16
|
+
readonly endsTurnTools: EndsTurnTools;
|
|
17
|
+
readonly promptMessages: readonly HarnessModelMessage[];
|
|
18
|
+
readonly requestEnvelopeTokens?: number;
|
|
19
|
+
readonly result: HarnessStepResult;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* One model step of the open turn: the prompt it reads, the model that serves it, and the call
|
|
23
|
+
* with its retries and recoveries. `onResponse` decides what the session does with the response.
|
|
24
|
+
*
|
|
25
|
+
* Approved work runs where the AI SDK ran it, between the step's start and the model call:
|
|
26
|
+
* approved workflow calls join their runs, the budget gate passes, then approved local calls run
|
|
27
|
+
* and the model reads their results.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runModelStep(step: Step, input: {
|
|
30
|
+
readonly onResponse: (response: ModelResponse) => Promise<StepResult>;
|
|
31
|
+
readonly turn: TurnInput;
|
|
32
|
+
readonly approved: ApprovedWork;
|
|
33
|
+
readonly generation: GenerationSteering;
|
|
34
|
+
/** A child's caller and a schedule hear only the turn's real end. */
|
|
35
|
+
readonly hidesHeldText: boolean;
|
|
36
|
+
/** The attempt the step's events belong to, for instrumentation. */
|
|
37
|
+
readonly setAttemptScope: (scope: InstrumentationAttempt | undefined) => void;
|
|
38
|
+
}): Promise<StepResult>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolveEffectiveRuntimeModel}from"./model.js";import{recoverModelCall}from"./recovery.js";import{recordModelUsage}from"./usage.js";import{ModelCaller}from"./call.js";import{reportModelCallFailure}from"./failure.js";import{HistoryStateKey}from"#context/keys.js";import{validateHarnessModelMessages}from"#harness/messages.js";import{activeTurnId}from"#harness/session-machine/view.js";import{startStep}from"#harness/session-machine/transitions.js";import{stepStartedForResolvers}from"#harness/session-machine/resolver-events.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{dispatchApprovedWorkflows,enforceBudget,hasApprovedWork,humanInputContext,runApprovedLocalCalls}from"#harness/hitl/index.js";import{requireSessionModelReference}from"#harness/types.js";import{failBoundaryEvent,failModelSelection}from"#harness/step/context.js";import{buildPrompt,previewPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";async function runModelStep(e,t){let{generation:n}=t,r=hasApprovedWork(e),i=r?previewPrompt(e,t.turn):await buildPrompt(e,t.turn),a=await selectModel(e,i);if(!(`model`in a))return a.failed;let start=t=>e.apply(startStep(e.view(),{modelId:requireSessionModelReference(e.session).id}),t),o=projectPrompt(e,i);try{await start(o)}catch(t){return failBoundaryEvent(e,t)}if(r&&await dispatchApprovedWorkflows(e,t.approved))return{next:null,session:e.session};let s=await enforceBudget(e,i.messages);if(s!==void 0)return s;if(r){let n=await runApprovedLocalCalls(e,t.approved,t.setAttemptScope);if(n!==void 0)return n;i=await buildPrompt(e,t.turn),o=projectPrompt(e,i)}let{approvedTools:c,pendingApprovalsNote:l}=humanInputContext(e),u=new ModelCaller(e,i,{approvedTools:c,generation:n,hidesHeldText:t.hidesHeldText,model:a.model,pendingApprovalsNote:l,projectedMessages:o,setAttemptScope:t.setAttemptScope,startStep:start,turnMessages:t.turn.messages}),d;try{d=await u.call({suppressStepStartedEmission:!0})}catch(t){if(u.throwIfCompactionFailed(),throwIfTurnAborted(e.config.abortSignal),n.interrupted)return u.steered();let r=await recoverModelCall({call:e=>u.call(e),error:t,sessionId:e.session.sessionId,turnId:e.position().turnId});if(u.throwIfCompactionFailed(),throwIfTurnAborted(e.config.abortSignal),n.interrupted)return u.steered();if(!(`result`in r))return reportModelCallFailure(e,r.error);d=r.result}await recordModelUsage(e,{model:a.model,result:d}),u.clearInterruptedUsage();let f;try{n.check(),f=await t.onResponse({coordinationTools:u.tools?.coordinationTools??e.config.tools,durableModelPromptMessageCount:i.clientContext===void 0||i.clientContext.messages.length===0?u.modelMessages.length:void 0,endsTurnTools:u.tools?.endsTurnTools??new Map,promptMessages:u.request.history,requestEnvelopeTokens:u.requestEnvelopeTokens,result:d})}catch(t){if(throwIfTurnAborted(e.config.abortSignal),n.interrupted)return u.steered();throw t}return e.ctx?.set(HistoryStateKey,u.request.historyState),f}async function selectModel(e,t){let{config:n,ctx:r}=e;try{if(r!==void 0&&n.dispatchDynamicModelEvent!==void 0){let i=e.position();await n.dispatchDynamicModelEvent({ctx:r,event:stepStartedForResolvers({modelId:e.session.agent.modelReference?.id??`dynamic`,sequence:i.sequence,stepIndex:i.stepIndex,turnId:activeTurnId(i)}),messages:validateHarnessModelMessages(e.projectHistory(withClientContext(t)))})}let i=await resolveEffectiveRuntimeModel({config:n,ctx:r,session:e.session});return e.session=i.session,{model:i.model}}catch(t){return{failed:await failModelSelection(e,t)}}}export{runModelStep};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { ToolSet } from "ai";
|
|
2
|
+
import type { HarnessToolDefinition } from "#harness/execute-tool.js";
|
|
3
|
+
import type { GenerationSteering } from "#harness/generation-steering.js";
|
|
4
|
+
import { type AnthropicCacheMarker } from "#harness/prompt-cache.js";
|
|
5
|
+
import type { Step } from "#harness/step/context.js";
|
|
6
|
+
import { type HarnessToolMap } from "#harness/types.js";
|
|
7
|
+
/** The tools one model call offers, and the views of them the step reads afterwards. */
|
|
8
|
+
export interface ModelTools {
|
|
9
|
+
/** What the AI SDK receives. */
|
|
10
|
+
readonly effectiveTools: ToolSet;
|
|
11
|
+
readonly modelTools: ToolSet;
|
|
12
|
+
/** Every tool the model can call, by name, for presenting its calls. */
|
|
13
|
+
readonly presentationTools: HarnessToolMap;
|
|
14
|
+
/** The advertised harness tools; they decide which calls defer to the runtime. */
|
|
15
|
+
readonly coordinationTools: HarnessToolMap;
|
|
16
|
+
/** Tools that can end the turn, with their `endsTurn` option. */
|
|
17
|
+
readonly endsTurnTools: EndsTurnTools;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Assembles the tools one model call offers: authored and dynamic subagent tools, task tools,
|
|
21
|
+
* provider tools, dynamic tools (which override a same-named authored tool), and `final_output`
|
|
22
|
+
* when the turn asks for a structured result.
|
|
23
|
+
*/
|
|
24
|
+
export declare function prepareModelTools(step: Step, input: {
|
|
25
|
+
readonly approvedTools: ReadonlySet<string>;
|
|
26
|
+
readonly model: import("ai").LanguageModel;
|
|
27
|
+
readonly disabledProviderTools?: ReadonlySet<string>;
|
|
28
|
+
readonly generation: GenerationSteering;
|
|
29
|
+
readonly marker: AnthropicCacheMarker | undefined;
|
|
30
|
+
}): Promise<ModelTools>;
|
|
31
|
+
/**
|
|
32
|
+
* Wired as the agent's `onToolExecutionEnd`. On the `tool-error` branch
|
|
33
|
+
* the `error` is still the original throwable (stack/cause intact),
|
|
34
|
+
* unlike the message-only `tool-error` part the model later sees.
|
|
35
|
+
*/
|
|
36
|
+
export declare function logToolExecutionError(event: {
|
|
37
|
+
readonly toolCall: {
|
|
38
|
+
readonly toolName: string;
|
|
39
|
+
readonly toolCallId: string;
|
|
40
|
+
};
|
|
41
|
+
readonly toolOutput: {
|
|
42
|
+
readonly type: string;
|
|
43
|
+
readonly error?: unknown;
|
|
44
|
+
};
|
|
45
|
+
}): void;
|
|
46
|
+
/** Appended to the model-facing description of every tool with `endsTurn: true`. */
|
|
47
|
+
export declare const ENDS_TURN_TOOL_NOTE = "Calling this tool ends your turn once it succeeds: do not write a reply or call other tools in the same step. If it fails, you will see the error and can continue.";
|
|
48
|
+
export type EndsTurnTools = ReadonlyMap<string, NonNullable<HarnessToolDefinition["endsTurn"]>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{toModelSchema}from"#tools/schema.js";import{resolveModelProvider}from"#internal/gateway.js";import{buildDynamicSubagentTools}from"#context/dynamic-subagent-lifecycle.js";import{isTurnCancellation}from"#harness/turn-cancellation.js";import{requireSessionModelReference}from"#harness/types.js";import{withTaskTools}from"#execution/tasks/model-step.js";import{buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#harness/final-output.js";import{applyLastToolCacheBreakpoint}from"#harness/prompt-cache.js";import{getAdvertisedTools}from"#harness/advertised-tools.js";const log=createLogger(`harness.tool-loop`);async function prepareModelTools(e,t){let{ctx:n}=e,{approvedTools:r,disabledProviderTools:i,marker:a}=t,o=withTaskTools(getAdvertisedTools({session:e.session,tools:buildHarnessToolsWithDynamicSubagents(e.config.tools,n)})),s=await buildToolSetWithProviderTools({approvedTools:r,disabledProviderTools:i,modelProvider:resolveModelProvider(t.model),modelReference:requireSessionModelReference(e.session),tools:o}),c=new Map(o);if(n!==void 0){let t=getAdvertisedTools({session:e.session,tools:buildDynamicTools(n)}),a=buildToolSetFromDefinitions({approvedTools:r,disabledProviderTools:i,tools:t});for(let[e,t]of Object.entries(a)){if(o.get(e)?.workflowId!==void 0)throw Error(`Dynamic tool "${e}" collides with a coordination-visible deferred tool.`);s[e]=t}let l=new Set;for(let e of t)l.has(e.name)||(l.add(e.name),c.set(e.name,e))}e.session.outputSchema!==void 0&&(s[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(e.session.outputSchema));let l=await getAdvertisedTools({modelTools:s,session:e.session,tools:o});e.session=l.session;let{modelTools:u}=l,d=new Map;if(!e.hasDelegatedCaller&&e.session.outputSchema===void 0)for(let[e,t]of Object.entries(u)){let n=c.get(e)?.endsTurn;t.type!==`provider`&&n!==void 0&&n!==!1&&(d.set(e,n),n===!0&&(t.description=`${t.description??``}\n\n${ENDS_TURN_TOOL_NOTE}`.trimStart()))}let f=a?applyLastToolCacheBreakpoint(u,a):u;for(let e of Object.values(f)){e.inputSchema=toModelSchema(e.inputSchema,`input`),e.outputSchema!==void 0&&(e.outputSchema=toModelSchema(e.outputSchema,`output`));let n=e.execute;n!==void 0&&(e.execute=(...e)=>(t.generation.protectToolExecution(),n(...e)))}return e.frameworkToolNames=new Set([...c].filter(([,e])=>e.frameworkTool===!0).map(([e])=>e)),{coordinationTools:o,effectiveTools:f,endsTurnTools:d,modelTools:u,presentationTools:c}}function logToolExecutionError(e){e.toolOutput.type!==`tool-error`||isTurnCancellation(e.toolOutput.error)||logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function buildHarnessToolsWithDynamicSubagents(e,t){let n=new Map(e);if(t===void 0)return n;for(let e of buildDynamicSubagentTools(t)){if(n.has(e.name))throw Error(`Dynamic subagent "${e.name}" collides with another runtime-visible tool name.`);n.set(e.name,e)}return n}const ENDS_TURN_TOOL_NOTE=`Calling this tool ends your turn once it succeeds: do not write a reply or call other tools in the same step. If it fails, you will see the error and can continue.`;export{ENDS_TURN_TOOL_NOTE,logToolExecutionError,prepareModelTools};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { LanguageModel, ProviderMetadata } from "ai";
|
|
2
|
+
import type { HarnessStepResult } from "#harness/step-hooks.js";
|
|
3
|
+
import { type TokenUsageDelta } from "#harness/turn-tag-state.js";
|
|
4
|
+
import type { Step } from "#harness/step/context.js";
|
|
5
|
+
/**
|
|
6
|
+
* The model's gateway id, or `undefined` for a model without a string `provider`, such as a
|
|
7
|
+
* test double, so a missing field never throws into the tool loop.
|
|
8
|
+
*/
|
|
9
|
+
export declare function gatewayModelId(model: LanguageModel): string | undefined;
|
|
10
|
+
export declare function extractTokenUsageDelta(input: {
|
|
11
|
+
readonly costUsd: number | undefined;
|
|
12
|
+
readonly usage: HarnessStepResult["usage"] | undefined;
|
|
13
|
+
}): TokenUsageDelta | undefined;
|
|
14
|
+
export declare function extractGatewayCostUsd(providerMetadata: ProviderMetadata | undefined): number | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Tags the turn's workflow run with the model and the turn's running token totals. Each model
|
|
17
|
+
* step is its own workflow step and attributes are last-write-wins, so the running total, kept in
|
|
18
|
+
* session state, is what reaches the dashboard. Best-effort: tagging never breaks the loop.
|
|
19
|
+
*/
|
|
20
|
+
export declare function recordModelUsage(step: Step, input: {
|
|
21
|
+
readonly model: LanguageModel;
|
|
22
|
+
readonly result: HarnessStepResult;
|
|
23
|
+
}): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{setEveAttributes}from"#runtime/attributes/emit.js";function gatewayModelId(e){try{return formatLanguageModelGatewayId(e)}catch{return}}function extractTokenUsageDelta(e){let t=e.usage;if(t!==void 0||e.costUsd!==void 0)return{cacheReadTokens:t?.inputTokenDetails?.cacheReadTokens,cacheWriteTokens:t?.inputTokenDetails?.cacheWriteTokens,costUsd:e.costUsd,inputTokens:t?.inputTokens,outputTokens:t?.outputTokens}}function extractGatewayCostUsd(e){let t=readGatewayMetadata(e)?.cost;if(typeof t==`number`&&Number.isFinite(t))return t;if(typeof t==`string`){let e=Number(t);return Number.isFinite(e)?e:void 0}}function readGatewayMetadata(e){let t=e?.gateway;return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}async function recordModelUsage(e,t){let n=accumulateTurnUsage({previous:getTurnUsageState(e.session.state),turnId:e.position().turnId,usage:extractTokenUsageDelta({costUsd:extractGatewayCostUsd(t.result.providerMetadata),usage:t.result.usage})});e.session=setTurnUsageState(e.session,n),await setEveAttributes({"$eve.model":gatewayModelId(t.model),"$eve.input_tokens":n.inputTokens,"$eve.output_tokens":n.outputTokens,"$eve.cache_read_tokens":n.cacheReadTokens,"$eve.cache_write_tokens":n.cacheWriteTokens,"$eve.cost_usd":n.sawCost?n.costUsd:void 0,"$eve.tool_count":e.config.tools.size})}export{extractGatewayCostUsd,extractTokenUsageDelta,gatewayModelId,recordModelUsage};
|