eve 0.19.0 → 0.21.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 +29 -0
- package/dist/src/channel/types.d.ts +9 -5
- package/dist/src/chunks/{use-eve-agent-Dvy_Wjvq.js → use-eve-agent-CM24ZUEI.js} +48 -34
- package/dist/src/chunks/{use-eve-agent-Bh1NmXO9.js → use-eve-agent-CxcKypLZ.js} +48 -34
- package/dist/src/cli/dev/tui/setup-selection-input.js +1 -1
- package/dist/src/cli/dev/tui/stream-format.d.ts +4 -0
- package/dist/src/cli/dev/tui/stream-format.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +1 -1
- package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +2 -0
- package/dist/src/cli/dev/tui/test/mock-terminal.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/message-reducer-types.d.ts +11 -3
- package/dist/src/client/message-reducer.js +1 -1
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-agent-config.js +1 -1
- package/dist/src/compiler/workspace-resources.js +1 -1
- package/dist/src/context/build-base-tool-context.d.ts +9 -0
- package/dist/src/context/build-base-tool-context.js +1 -0
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-skill-lifecycle.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/keys.d.ts +0 -1
- package/dist/src/context/keys.js +1 -1
- package/dist/src/discover/sandbox.d.ts +0 -6
- package/dist/src/discover/sandbox.js +1 -1
- package/dist/src/evals/cli/eval.js +4 -1
- package/dist/src/evals/runner/discover.d.ts +10 -0
- package/dist/src/evals/runner/discover.js +1 -1
- package/dist/src/execution/create-session-step.d.ts +2 -1
- package/dist/src/execution/create-session-step.js +1 -1
- package/dist/src/execution/delegated-parent-notification.d.ts +6 -0
- package/dist/src/execution/delegated-parent-notification.js +1 -1
- package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
- package/dist/src/execution/dispatch-workflow-runtime-actions-step.js +1 -1
- package/dist/src/execution/durable-session-migrations/turn-workflow.d.ts +2 -0
- package/dist/src/execution/durable-session-store.d.ts +1 -0
- package/dist/src/execution/next-driver-action.d.ts +3 -0
- package/dist/src/execution/node-step.d.ts +8 -0
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/run-session-limits.d.ts +21 -0
- package/dist/src/execution/run-session-limits.js +1 -0
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/sandbox/abort-bound-session.d.ts +6 -0
- package/dist/src/execution/sandbox/abort-bound-session.js +1 -0
- package/dist/src/execution/sandbox/active-handles.d.ts +29 -0
- package/dist/src/execution/sandbox/active-handles.js +1 -0
- package/dist/src/execution/sandbox/bindings/docker.d.ts +2 -2
- package/dist/src/execution/sandbox/bindings/docker.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/local-backend-utils.d.ts +1 -1
- package/dist/src/execution/sandbox/bindings/local-backend-utils.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-provider-state.d.ts +11 -0
- package/dist/src/execution/sandbox/bindings/microsandbox-provider-state.js +1 -0
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.d.ts +7 -4
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/ensure.js +1 -1
- package/dist/src/execution/sandbox/prewarm.js +1 -1
- package/dist/src/execution/sandbox/require-sandbox.d.ts +3 -1
- package/dist/src/execution/sandbox/require-sandbox.js +1 -1
- package/dist/src/execution/session-callback-step.d.ts +6 -0
- package/dist/src/execution/session-callback-step.js +1 -1
- package/dist/src/execution/session.d.ts +14 -3
- package/dist/src/execution/session.js +2 -4
- package/dist/src/execution/skills/instructions.d.ts +8 -4
- package/dist/src/execution/skills/instructions.js +2 -2
- package/dist/src/execution/subagent-tool.d.ts +7 -0
- package/dist/src/execution/subagent-tool.js +1 -1
- package/dist/src/execution/subagent-usage-span.d.ts +9 -0
- package/dist/src/execution/subagent-usage-span.js +1 -0
- package/dist/src/execution/tool-auth.d.ts +2 -1
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/execution/turn-execution-cursor.d.ts +2 -0
- package/dist/src/execution/turn-workflow.js +1 -1
- package/dist/src/execution/web-fetch/tool.d.ts +6 -1
- package/dist/src/execution/web-fetch/tool.js +1 -1
- package/dist/src/execution/workflow-entry.d.ts +1 -0
- package/dist/src/execution/workflow-entry.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/execution/workflow-skill-root.d.ts +6 -0
- package/dist/src/execution/workflow-skill-root.js +1 -0
- package/dist/src/execution/workflow-steps.d.ts +3 -0
- package/dist/src/execution/workflow-steps.js +1 -1
- package/dist/src/harness/advertised-tools.d.ts +1 -0
- package/dist/src/harness/advertised-tools.js +1 -1
- package/dist/src/harness/attachment-staging.js +1 -1
- package/dist/src/harness/compaction.d.ts +1 -1
- package/dist/src/harness/compaction.js +1 -1
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/execute-tool.d.ts +2 -1
- package/dist/src/harness/input-requests.d.ts +8 -0
- package/dist/src/harness/input-requests.js +1 -1
- package/dist/src/harness/model-call-error.js +1 -1
- package/dist/src/harness/runtime-actions.js +1 -1
- package/dist/src/harness/session-limit-continuation.d.ts +55 -0
- package/dist/src/harness/session-limit-continuation.js +1 -0
- package/dist/src/harness/session-limit-enforcement.d.ts +55 -0
- package/dist/src/harness/session-limit-enforcement.js +1 -0
- package/dist/src/harness/step-hooks.d.ts +1 -1
- package/dist/src/harness/step-hooks.js +1 -1
- package/dist/src/harness/subagent-depth.d.ts +1 -4
- package/dist/src/harness/subagent-depth.js +1 -1
- package/dist/src/harness/subagent-token-budget.d.ts +14 -0
- package/dist/src/harness/subagent-token-budget.js +1 -0
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.d.ts +2 -3
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/harness/turn-cancellation.d.ts +8 -0
- package/dist/src/harness/turn-cancellation.js +1 -0
- package/dist/src/harness/turn-tag-state.d.ts +33 -0
- package/dist/src/harness/turn-tag-state.js +1 -1
- package/dist/src/harness/types.d.ts +23 -4
- package/dist/src/harness/workflow-sandbox.d.ts +1 -0
- package/dist/src/harness/workflow-sandbox.js +1 -1
- package/dist/src/harness/workflow-subagent-limit.d.ts +38 -0
- package/dist/src/harness/workflow-subagent-limit.js +1 -0
- package/dist/src/harness/workflow-tool-description.d.ts +6 -1
- package/dist/src/harness/workflow-tool-description.js +5 -3
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-definition/core.js +1 -1
- package/dist/src/internal/authored-definition/schema-backed.js +1 -1
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.d.ts +40 -0
- package/dist/src/internal/nitro/host/sandbox-shutdown-plugin.js +1 -0
- package/dist/src/internal/nitro/host/start-production-server.js +1 -1
- package/dist/src/protocol/message.d.ts +31 -2
- package/dist/src/protocol/message.js +2 -2
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +34 -3
- package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
- package/dist/src/public/channels/chat-sdk/index.d.ts +2 -0
- package/dist/src/public/channels/chat-sdk/index.js +1 -1
- package/dist/src/public/channels/chat-sdk/messageToUserContent.d.ts +13 -0
- package/dist/src/public/channels/chat-sdk/messageToUserContent.js +1 -0
- package/dist/src/public/channels/chat-sdk/notImplemented.d.ts +7 -0
- package/dist/src/public/channels/chat-sdk/notImplemented.js +1 -0
- package/dist/src/public/channels/slack/api.d.ts +14 -12
- package/dist/src/public/channels/slack/api.js +1 -1
- package/dist/src/public/definitions/approval.d.ts +4 -1
- package/dist/src/public/definitions/tool.d.ts +44 -0
- package/dist/src/public/definitions/tool.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -1
- package/dist/src/public/tools/index.js +1 -1
- package/dist/src/public/tools/internal.d.ts +3 -2
- package/dist/src/public/tools/internal.js +1 -1
- package/dist/src/runtime/actions/types.d.ts +9 -0
- package/dist/src/runtime/actions/types.js +1 -1
- package/dist/src/runtime/agent/bootstrap.d.ts +2 -0
- package/dist/src/runtime/agent/bootstrap.js +1 -1
- package/dist/src/runtime/connections/mcp-client.d.ts +2 -2
- package/dist/src/runtime/connections/mcp-client.js +1 -1
- package/dist/src/runtime/connections/openapi-client.d.ts +2 -2
- package/dist/src/runtime/connections/openapi-client.js +1 -1
- package/dist/src/runtime/connections/types.d.ts +6 -1
- package/dist/src/runtime/framework-tools/bash.js +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
- package/dist/src/runtime/framework-tools/glob.js +1 -1
- package/dist/src/runtime/framework-tools/grep.js +1 -1
- package/dist/src/runtime/framework-tools/read-file.js +1 -1
- package/dist/src/runtime/framework-tools/web-fetch.js +1 -1
- package/dist/src/runtime/framework-tools/write-file.js +1 -1
- package/dist/src/runtime/resolve-agent.js +1 -1
- package/dist/src/runtime/sandbox/keys.js +1 -1
- package/dist/src/runtime/sandbox/template-plan.js +1 -1
- package/dist/src/runtime/session-callback-route.js +1 -1
- package/dist/src/runtime/skills/sandbox-access.d.ts +1 -1
- package/dist/src/runtime/skills/sandbox-access.js +1 -1
- package/dist/src/runtime/workspace/seed-files.js +1 -1
- package/dist/src/sandbox/state.d.ts +0 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/scaffold/create/web-template.d.ts +2 -2
- package/dist/src/setup/scaffold/create/web-template.js +77 -3
- package/dist/src/shared/agent-definition.d.ts +31 -3
- package/dist/src/shared/dynamic-tool-definition.d.ts +4 -1
- package/dist/src/shared/sandbox-backend.d.ts +7 -1
- package/dist/src/shared/skill-package.d.ts +2 -2
- package/dist/src/shared/skill-package.js +1 -1
- package/dist/src/shared/skill-paths.d.ts +28 -0
- package/dist/src/shared/skill-paths.js +2 -0
- package/dist/src/shared/token-usage.d.ts +22 -0
- package/dist/src/shared/token-usage.js +1 -0
- package/dist/src/shared/tool-definition.d.ts +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/agent-config.md +32 -15
- package/docs/channels/chat-sdk.mdx +209 -0
- package/docs/channels/meta.json +1 -0
- package/docs/concepts/context-control.md +2 -2
- package/docs/concepts/default-harness.md +10 -0
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/guides/client/messages.mdx +4 -0
- package/docs/guides/client/streaming.mdx +17 -12
- package/docs/guides/dynamic-workflows.md +87 -0
- package/docs/guides/frontend/overview.mdx +5 -1
- package/docs/guides/meta.json +1 -0
- package/docs/guides/remote-agents.md +1 -0
- package/docs/reference/project-layout.md +5 -4
- package/docs/reference/typescript-api.md +26 -26
- package/docs/sandbox.mdx +4 -2
- package/docs/skills.mdx +3 -1
- package/docs/subagents.mdx +2 -1
- package/docs/tools/human-in-the-loop.md +1 -1
- package/docs/tools/overview.mdx +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createInputRequestedEvent,createSessionCompletedEvent,createTurnCompletedEvent}from"#protocol/message.js";import{emitFailedStep,emitTurnEpilogue,setHarnessEmissionState}from"#harness/emission.js";import{setPendingInputBatch}from"#harness/input-requests.js";import{extendSessionTokenBudget,getSessionTokenLimitViolation,getSessionTokenUsage}from"#harness/turn-tag-state.js";import{createSessionLimitContinuationRequest}from"#harness/session-limit-continuation.js";async function applySessionLimitContinuation(e){if(e.limitContinuation===void 0)return{result:null,session:e.session};if(e.limitContinuation.granted)return{result:null,session:extendSessionTokenBudget(e.session)};let r=getSessionTokenLimitViolation(e.session);return r===null?{result:null,session:e.session}:e.config.mode===`task`?{result:await failSessionTokenLimit({...e,violation:r}),session:e.session}:(e.emit&&(await e.emit(createTurnCompletedEvent({sequence:e.emissionState.sequence,turnId:e.emissionState.turnId})),await e.emit(createSessionCompletedEvent())),{result:{next:{done:!0,output:``},session:e.session},session:e.session})}async function enforceSessionTokenLimit(e){let t=getSessionTokenLimitViolation(e.session);if(t===null)return null;let{emit:n}=e;return n!==void 0&&(e.config.mode===`conversation`||e.config.capabilities?.requestInput===!0)?parkOnSessionTokenLimit({...e,emit:n,violation:t}):failSessionTokenLimit({...e,violation:t})}async function parkOnSessionTokenLimit(t){let n=getSessionTokenUsage(t.session),r=createSessionLimitContinuationRequest({sessionId:t.session.sessionId,totalUsedTokens:t.violation.kind===`input`?n.inputTokens:n.outputTokens,violation:t.violation}),a=t.emissionState,o=setPendingInputBatch({event:{sequence:a.sequence,stepIndex:a.stepIndex,turnId:a.turnId},requests:[r],responseMessages:[],session:{...t.session,history:[...t.messages]}});return await t.emit(createInputRequestedEvent({requests:[r],sequence:a.sequence,stepIndex:a.stepIndex,turnId:a.turnId})),t.config.mode===`conversation`&&(a=await emitTurnEpilogue(t.emit,a,t.config.mode)),{next:null,session:setHarnessEmissionState(o,a)}}function formatSessionTokenLimitMessage(e){return`The session reached its configured ${e} token limit.`}async function failSessionTokenLimit(e){let t=getSessionTokenUsage(e.session),n=formatSessionTokenLimitMessage(e.violation.kind),i={inputTokens:t.inputTokens,kind:e.violation.kind,limit:e.violation.limit,outputTokens:t.outputTokens,usedTokens:e.violation.usedTokens};return e.emit&&await emitFailedStep(e.emit,e.emissionState,{code:`SESSION_TOKEN_LIMIT_REACHED`,details:i,message:n,sessionId:e.session.sessionId}),{next:{done:!0,isError:e.config.mode===`task`?!0:void 0,output:e.config.mode===`task`?n:``},session:e.session}}export{applySessionLimitContinuation,enforceSessionTokenLimit};
|
|
@@ -8,7 +8,7 @@ import type { HarnessEmitFn, HarnessSession, ToolLoopHarnessConfig } from "#harn
|
|
|
8
8
|
* Used by both the streaming (`onStepFinish` callback) and non-streaming
|
|
9
9
|
* (`generateText` result) code paths.
|
|
10
10
|
*/
|
|
11
|
-
export type HarnessStepResult = Pick<StepResult<ToolSet>, "content" | "finishReason" | "response" | "text" | "toolCalls" | "toolResults" | "usage">;
|
|
11
|
+
export type HarnessStepResult = Pick<StepResult<ToolSet>, "content" | "finishReason" | "providerMetadata" | "response" | "text" | "toolCalls" | "toolResults" | "usage">;
|
|
12
12
|
/**
|
|
13
13
|
* Input for {@link buildStepHooks}.
|
|
14
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createActionResultEvent,createActionsRequestedEvent,createStepCompletedEvent}from"#protocol/message.js";import{contextStorage}from"#context/container.js";import{emitStepStarted,normalizeAssistantStepFinishReason}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall}from"#harness/runtime-actions.js";import{isAuthorizationSignal,isPendingAuthorizationToolOutput}from"#harness/authorization.js";import{createRuntimeToolResultFromMessagePart,createRuntimeToolResultFromStepResult,createRuntimeToolResultFromToolError}from"#harness/action-result-helpers.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyConversationCacheControl,mergeGatewayAutoCaching}from"#harness/prompt-cache.js";function buildStepHooks(e){let t=e.session,n=e.emit,r;return{onStepFinish:async e=>{r(e)},prepareStep:async({messages:r})=>{let a=r;n&&e.emitStepStarted!==!1&&await emitStepStarted(n,e.emissionState,r),e.cachePath.kind===`anthropic-direct`&&e.marker&&(a=applyConversationCacheControl([...r],e.marker));let o={messages:a};return e.cachePath.kind===`gateway-auto`&&(o.providerOptions=mergeGatewayAutoCaching(t.agent.modelReference.providerOptions)),o},stepResult:new Promise(e=>{r=e})}}async function emitStepActions(r,i,s,c){let l=new Set(s.toolCalls.filter(isProviderExecutedToolCall).map(e=>e.toolCallId)),u=new Set([...l,...extractToolApprovalInputRequests({content:s.content??[]}).map(e=>e.action.callId),...s.toolCalls.filter(isInvalidToolCall).map(e=>e.toolCallId)]),isExcluded=(e,t)=>u.has(e)||c.excludedActionToolNames.has(t),d=s.toolCalls.filter(e=>!isExcluded(e.toolCallId,e.toolName)&&!c.emittedActionCallIds?.has(e.toolCallId)).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:c.tools}));d.length>0&&await r(createActionsRequestedEvent({actions:d,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId}));let f=c.handledInlineToolResultCallIds,p=new Map(s.toolResults.map(e=>[e.toolCallId,e.output]));for(let t of reconcileToolResults(s)){if(isExcluded(t.callId,t.toolName)||f?.has(t.callId))continue;let n=p.get(t.callId);shouldSkipAuthorizationActionResult(t.callId,n)||await r(createActionResultEvent({result:t,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId}))}await r(createStepCompletedEvent({finishReason:normalizeAssistantStepFinishReason(s.finishReason),sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId,usage:extractStepUsage(s.usage)}))}function isInvalidToolCall(e){return e.invalid===!0}function isProviderExecutedToolCall(e){return e.providerExecuted===!0}function reconcileToolResults(e){let t=new Map;for(let n of e.toolResults)n.providerExecuted!==!0&&t.set(n.toolCallId,createRuntimeToolResultFromStepResult(n));for(let n of e.content??[])n.type!==`tool-error`||n.providerExecuted===!0||t.has(n.toolCallId)||t.set(n.toolCallId,createRuntimeToolResultFromToolError(n));for(let n of extractToolResultParts(e.response.messages))n.providerExecuted!==!0&&(t.has(n.toolCallId)||t.set(n.toolCallId,createRuntimeToolResultFromMessagePart(n)));return[...t.values()]}function shouldSkipAuthorizationActionResult(e,t){if(t!==void 0&&isPendingAuthorizationToolOutput(t))return!0;let n=contextStorage.getStore();if(n===void 0)return!1;let i=readToolInterrupt(n,e);return i!==void 0&&isAuthorizationSignal(i)}function extractToolResultParts(e){let t=[];for(let n of e)if(!(n.role!==`tool`||!Array.isArray(n.content)))for(let e of n.content)e.type===`tool-result`&&t.push(e);return t}function extractStepUsage(e){
|
|
1
|
+
import{createActionResultEvent,createActionsRequestedEvent,createStepCompletedEvent}from"#protocol/message.js";import{contextStorage}from"#context/container.js";import{emitStepStarted,normalizeAssistantStepFinishReason}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall}from"#harness/runtime-actions.js";import{isAuthorizationSignal,isPendingAuthorizationToolOutput}from"#harness/authorization.js";import{createRuntimeToolResultFromMessagePart,createRuntimeToolResultFromStepResult,createRuntimeToolResultFromToolError}from"#harness/action-result-helpers.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyConversationCacheControl,mergeGatewayAutoCaching}from"#harness/prompt-cache.js";function buildStepHooks(e){let t=e.session,n=e.emit,r;return{onStepFinish:async e=>{r(e)},prepareStep:async({messages:r})=>{let a=r;n&&e.emitStepStarted!==!1&&await emitStepStarted(n,e.emissionState,r),e.cachePath.kind===`anthropic-direct`&&e.marker&&(a=applyConversationCacheControl([...r],e.marker));let o={messages:a};return e.cachePath.kind===`gateway-auto`&&(o.providerOptions=mergeGatewayAutoCaching(t.agent.modelReference.providerOptions)),o},stepResult:new Promise(e=>{r=e})}}async function emitStepActions(r,i,s,c){let l=new Set(s.toolCalls.filter(isProviderExecutedToolCall).map(e=>e.toolCallId)),u=new Set([...l,...extractToolApprovalInputRequests({content:s.content??[]}).map(e=>e.action.callId),...s.toolCalls.filter(isInvalidToolCall).map(e=>e.toolCallId)]),isExcluded=(e,t)=>u.has(e)||c.excludedActionToolNames.has(t),d=s.toolCalls.filter(e=>!isExcluded(e.toolCallId,e.toolName)&&!c.emittedActionCallIds?.has(e.toolCallId)).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:c.tools}));d.length>0&&await r(createActionsRequestedEvent({actions:d,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId}));let f=c.handledInlineToolResultCallIds,p=new Map(s.toolResults.map(e=>[e.toolCallId,e.output]));for(let t of reconcileToolResults(s)){if(isExcluded(t.callId,t.toolName)||f?.has(t.callId))continue;let n=p.get(t.callId);shouldSkipAuthorizationActionResult(t.callId,n)||await r(createActionResultEvent({result:t,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId}))}await r(createStepCompletedEvent({finishReason:normalizeAssistantStepFinishReason(s.finishReason),providerMetadata:extractStepProviderMetadata(s.providerMetadata),sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId,usage:extractStepUsage({costUsd:extractGatewayCostUsd(s.providerMetadata),usage:s.usage})}))}function isInvalidToolCall(e){return e.invalid===!0}function isProviderExecutedToolCall(e){return e.providerExecuted===!0}function reconcileToolResults(e){let t=new Map;for(let n of e.toolResults)n.providerExecuted!==!0&&t.set(n.toolCallId,createRuntimeToolResultFromStepResult(n));for(let n of e.content??[])n.type!==`tool-error`||n.providerExecuted===!0||t.has(n.toolCallId)||t.set(n.toolCallId,createRuntimeToolResultFromToolError(n));for(let n of extractToolResultParts(e.response.messages))n.providerExecuted!==!0&&(t.has(n.toolCallId)||t.set(n.toolCallId,createRuntimeToolResultFromMessagePart(n)));return[...t.values()]}function shouldSkipAuthorizationActionResult(e,t){if(t!==void 0&&isPendingAuthorizationToolOutput(t))return!0;let n=contextStorage.getStore();if(n===void 0)return!1;let i=readToolInterrupt(n,e);return i!==void 0&&isAuthorizationSignal(i)}function extractToolResultParts(e){let t=[];for(let n of e)if(!(n.role!==`tool`||!Array.isArray(n.content)))for(let e of n.content)e.type===`tool-result`&&t.push(e);return t}function extractStepUsage(e){let t={};e.costUsd!==void 0&&(t.costUsd=e.costUsd);let n=e.usage;return n===void 0?Object.keys(t).length>0?t:void 0:(n.inputTokens!==void 0&&(t.inputTokens=n.inputTokens),n.outputTokens!==void 0&&(t.outputTokens=n.outputTokens),n.inputTokenDetails?.cacheReadTokens!==void 0&&(t.cacheReadTokens=n.inputTokenDetails.cacheReadTokens),n.inputTokenDetails?.cacheWriteTokens!==void 0&&(t.cacheWriteTokens=n.inputTokenDetails.cacheWriteTokens),Object.keys(t).length>0?t:void 0)}function extractStepProviderMetadata(e){let t=readGatewayGenerationId(e);return t===void 0?void 0:{gateway:{generationId:t}}}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 readGatewayGenerationId(e){let t=readGatewayMetadata(e)?.generationId;return typeof t==`string`&&t.length>0?t:void 0}function readGatewayMetadata(e){let t=e?.gateway;return t&&typeof t==`object`&&!Array.isArray(t)?t:void 0}export{buildStepHooks,emitStepActions,isInvalidToolCall};
|
|
@@ -9,9 +9,6 @@ export type SubagentDelegationLimit = {
|
|
|
9
9
|
readonly reached: boolean;
|
|
10
10
|
};
|
|
11
11
|
export declare function resolveSubagentDelegationLimit(session: Pick<HarnessSession, "subagentDepth" | "subagentMaxDepth">): SubagentDelegationLimit;
|
|
12
|
-
export declare function
|
|
13
|
-
readonly subagentDepth?: number;
|
|
14
|
-
readonly subagentMaxDepth?: number;
|
|
15
|
-
};
|
|
12
|
+
export declare function readSerializedSubagentDepth(serializedContext: Readonly<Record<string, unknown>>): number | undefined;
|
|
16
13
|
export declare function isSubagentDelegationAction(action: RuntimeActionRequest): action is DelegatedRuntimeActionRequest;
|
|
17
14
|
export declare function getSubagentDelegationName(action: DelegatedRuntimeActionRequest): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SubagentDepthKey
|
|
1
|
+
import{SubagentDepthKey}from"#context/keys.js";const DEFAULT_SUBAGENT_MAX_DEPTH=3;function resolveSubagentDelegationLimit(e){let t=parseSubagentDepth(e.subagentDepth),n=parseSubagentMaxDepth(e.subagentMaxDepth)??3;return{currentDepth:t,maxDepth:n,nextChildDepth:t+1,reached:t>=n}}function readSerializedSubagentDepth(t){let n=parseSubagentDepth(t[SubagentDepthKey.name]);return n===0?void 0:n}function isSubagentDelegationAction(e){return e.kind===`subagent-call`||e.kind===`remote-agent-call`}function getSubagentDelegationName(e){switch(e.kind){case`remote-agent-call`:return e.remoteAgentName;case`subagent-call`:return e.subagentName;default:return e}}function parseSubagentDepth(e){return typeof e==`number`&&Number.isInteger(e)&&e>0?e:0}function parseSubagentMaxDepth(e){return typeof e==`number`&&Number.isInteger(e)&&e>0?e:void 0}export{DEFAULT_SUBAGENT_MAX_DEPTH,getSubagentDelegationName,isSubagentDelegationAction,readSerializedSubagentDepth,resolveSubagentDelegationLimit};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RunSessionLimits } from "#channel/types.js";
|
|
2
|
+
import type { HarnessSession } from "#harness/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Computes the session token limits a delegated child inherits from its parent:
|
|
5
|
+
* the remaining quota (configured limit minus accumulated usage) split evenly
|
|
6
|
+
* across the batch's delegated calls, per axis, at dispatch time. `false`
|
|
7
|
+
* marks an axis with no inherited cap.
|
|
8
|
+
*
|
|
9
|
+
* Splitting by `fanoutSize` makes one dispatch batch collectively
|
|
10
|
+
* bounded by the parent's remainder. N parallel children cannot each spend
|
|
11
|
+
* the full remainder. Sequential batches see the quota net of completed
|
|
12
|
+
* children because their usage folds back into the parent's session totals.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveRemainingSessionTokenLimits(session: Pick<HarnessSession, "limits" | "state">, fanoutSize?: number): RunSessionLimits;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getSessionTokenUsage}from"#harness/turn-tag-state.js";function resolveRemainingSessionTokenLimits(t,n=1){let r=Math.max(1,Math.floor(n)),i=getSessionTokenUsage(t);return{maxInputTokensPerSession:grantShare(remainingQuota(t.limits?.maxInputTokensPerSession,i.inputTokens),r),maxOutputTokensPerSession:grantShare(remainingQuota(t.limits?.maxOutputTokensPerSession,i.outputTokens),r)}}function remainingQuota(e,t){return e===void 0?!1:Math.max(0,e-t)}function grantShare(e,t){return e===!1?!1:Math.floor(e/t)}export{resolveRemainingSessionTokenLimits};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{isScheduleAppAuth}from"#channel/schedule-auth.js";import{AuthKey,ParentSessionKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{toErrorMessage}from"#shared/errors.js";import{createActionResultEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{clearPendingWorkflowInterrupt,getPendingWorkflowInterrupt,setPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getWorkflowRuntimeActionInterrupts,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{getWorkflowContinuationSecurity,readWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{buildWorkflowHostTools}from"#harness/workflow-sandbox.js";import{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{createWorkflowLifecycle}from"#harness/workflow-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{accumulateTurnUsage,getSessionTokenLimitViolation,getSessionTokenUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{normalizeProviderToolHistory}from"#harness/provider-tool-history.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{getAdvertisedTools}from"#harness/advertised-tools.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{buildToolApproval,buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{continueWorkflowSandboxInterrupt,getWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult}from"#shared/workflow-sandbox.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,c=getInstrumentationConfig();c!==void 0&&ensureOtelIntegration();let f=c===void 0?void 0:trace.getTracer(`eve`),p=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(f&&hasStepInput(t)){let t=c?.functionId??p,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=f.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(f,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(f,v,y){let b=f;y&&(b=setTurnTraceState(b,y.spanContext()));let x=getHarnessEmissionState(b.state),S=consumeDeferredStepInput({input:v,session:b});b=S.session;let D=await resolvePendingRuntimeActions({emit:n,session:b,stepInput:S.input});if(D.outcome===`unresolved`)return{next:null,session:D.session};b=D.session;let A=resolvePendingInput({history:D.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:b,stepInput:S.input});if(A.outcome===`unresolved`)return n&&A.deferredMessage===!0&&hasStepInput(v)?(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),x=await emitTurnEpilogue(n,x,t.mode),{next:null,session:setHarnessEmissionState(A.session,x)}):{next:null,session:A.session};if(n&&A.rejectedActions)for(let e of A.rejectedActions.results)await n(createActionResultEvent({rejected:!0,result:e,sequence:A.rejectedActions.event.sequence,stepIndex:A.rejectedActions.event.stepIndex,turnId:A.rejectedActions.event.turnId}));n&&hasStepInput(v)&&(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),b=setHarnessEmissionState(b,x),y&&y.setAttribute(`eve.turn.id`,x.turnId)),b=A.session;let j=A.messages;if(S.input?.context!==void 0)for(let e of S.input.context)j.push({content:e,role:`user`});if(S.input?.message!==void 0&&!A.deferredMessage&&!A.consumedMessage){let e=await stageAttachmentsToSandbox(S.input.message);j.push({content:e,role:`user`})}let M=await t.resolveModel(b.agent.modelReference),N=detectPromptCachePath(M),P=N.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,F=buildGatewayAttributionHeaders(M,t.runtimeIdentity);({messages:j,session:b}=await maybeCompact({emit:n,emissionState:x,headers:F,messages:j,model:M,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:b,telemetry:enrichTelemetry(c,p)??void 0}));let I=getApprovedTools(b),L=contextStorage.getStore(),R=b.outputSchema===void 0&&L!==void 0&&isScheduleAppAuth(L.get(AuthKey))&&L.get(ParentSessionKey)===void 0,z=await hydrateSandboxAttachments(j),B=[],V=[];for(let e of z)e.role===`system`?B.push(e):V.push(e);if(L!==void 0){B.push(...buildDynamicInstructionMessages(L));let e=L.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&B.push({role:`system`,content:e})}R&&B.push({role:`system`,content:CONDITIONAL_DELIVERY_INSTRUCTION});let H=V,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=b.agent.system?[{role:`system`,content:b.agent.system}]:[],r=B.length>0||t.length>0?[...t,...n,...B]:void 0,i=r!==void 0&&P?applySystemCacheBreakpoint(r,P):r??b.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:c,emissionState:x,environment,modelInput:{instructions:i,messages:H},session:b})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let o=e.trailingUserNote?[...H,{role:`user`,content:e.trailingUserNote}]:H,s=getAdvertisedTools({session:b,tools:t.tools}),u=await buildToolSetWithProviderTools({approvedTools:I,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:b.agent.modelReference,tools:s});if(L!==void 0){let n=getAdvertisedTools({session:b,tools:buildDynamicTools(L)}),r=buildToolSetFromDefinitions({approvedTools:I,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,tools:n});for(let[e,t]of Object.entries(r))u[e]=t}b.outputSchema!==void 0&&(u[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(b.outputSchema));let d=n===void 0?void 0:({tools:e})=>createWorkflowLifecycle({emit:n,emissionState:x,tools:e}),f=t.workflow===!0?{lifecycle:d}:void 0,h=await getAdvertisedTools({modelTools:u,session:b,tools:s,workflow:f});b=h.session;let g=h.modelTools,_=P?applyLastToolCacheBreakpoint(g,P):g,v=buildStepHooks({cachePath:N,emit:n,emissionState:x,emitStepStarted:e.suppressStepStartedEmission!==!0,marker:P,session:b}),y=new ToolLoopAgent({headers:F,instructions:i,model:M,onToolExecutionEnd:logToolExecutionError,onError(e){summarizeKnownModelCallConfigError(e.error)===null&&logError(log,`tool-loop stream error`,e.error)},onStepFinish:v.onStepFinish,prepareStep:v.prepareStep,reasoning:b.agent.reasoning,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(c,p,a),toolApproval:buildToolApproval(g),tools:_}),executeModelCall=async()=>{if(n){let e=[...t.tools].filter(([e,t])=>t.runtimeAction!==void 0&&s.get(e)===void 0).map(([e])=>e),r=new Set([ASK_QUESTION_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME,...e]),i=await y.stream({messages:o}),{emittedActionCallIds:a,handledInlineToolResultCallIds:c,inlineAuthorizationResults:u,inlineToolResultParts:d,trailingInlineToolResultParts:f}=await emitStreamContent(n,x,i.fullStream,{excludedActionToolNames:r,tools:t.tools}),p=await v.stepResult;if(isEmptyModelResponse(p)&&d.length===0&&u.length===0&&f.length===0)throw new EmptyModelResponseError;if(await emitStepActions(n,x,p,{emittedActionCallIds:a,excludedActionToolNames:r,handledInlineToolResultCallIds:c,tools:s}),d.length>0||u.length>0||f.length>0){let e=p.toolResults,t=new Map(e.map(e=>[e.toolCallId,e]));for(let e of u)t.set(e.toolCallId,e);return{content:p.content,finishReason:p.finishReason,response:{...p.response,...d.length>0||f.length>0?{messages:insertInlineToolResultMessages({append:f,prepend:d,responseMessages:p.response.messages})}:{}},text:p.text,toolCalls:p.toolCalls,toolResults:[...t.values()],usage:p.usage}}return p}await y.generate({messages:o});let e=await v.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:b.sessionId,turnId:x.turnId})},U=prepareModelCallInput();n&&await emitStepStarted(n,x,j);let W=await continuePendingWorkflowInterrupt({childResults:S.input?.runtimeActionResults,config:t,emit:n,emissionState:x,runStep,session:b});if(W!==null)return W;let G=getSessionTokenLimitViolation(b);if(G!==null)return failSessionTokenLimit({config:t,emit:n,emissionState:x,session:b,violation:G});let K;try{K=await runOneModelCall({preparedInput:U,suppressStepStartedEmission:!0})}catch(r){let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId}),e=>attemptEmptyResponseRecovery({emptyDeliveryEnabled:R,error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId})]});if(a.outcome===`recovered`)K=a.result;else{let r=a.error;if(y&&recordErrorOnSpan(y,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:b.sessionId,turnId:x.turnId}),x=await emitRecoverableFailedTurn(n,x,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(b,x)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,f=l===null?summarizeKnownModelCallRequestError(r):null,p=l?.message??f?.message??toErrorMessage(r),_=extractModelCallErrorDetails(r),v=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:_,requestSummary:f}),S=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:_,requestSummary:f,sessionId:b.sessionId,turnId:x.turnId});return s===`terminal`?(l===null?log.error(f?.message??`model call failed terminally`,S):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:b.sessionId,turnId:x.turnId}),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:t.mode===`task`?{done:!0,isError:!0,output:p}:{done:!0,output:``},session:b}):t.mode===`task`?(log.error(f?.message??`model call failed; failing the task run`,S),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,isError:!0,output:p},session:b}):(log.error(f?.message??`model call failed — parking session for retry by the user`,S),x=await emitRecoverableFailedTurn(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p}),{next:null,session:setHarnessEmissionState(b,x)})}}let q=accumulateTurnUsage({previous:getTurnUsageState(b.state),turnId:x.turnId,usage:extractTokenUsageDelta(K.usage)});b=setTurnUsageState(b,q);let J;try{J=formatLanguageModelGatewayId(M)}catch{J=void 0}return await setEveAttributes({"$eve.model":J,"$eve.input_tokens":q.inputTokens,"$eve.output_tokens":q.outputTokens,"$eve.cache_read_tokens":q.cacheReadTokens,"$eve.cache_write_tokens":q.cacheWriteTokens,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:x,promptMessages:j,result:K,runStep,session:b})}return runStep}function extractTokenUsageDelta(e){if(e!==void 0)return{cacheReadTokens:e.inputTokenDetails?.cacheReadTokens,cacheWriteTokens:e.inputTokenDetails?.cacheWriteTokens,inputTokens:e.inputTokens,outputTokens:e.outputTokens}}function formatSessionTokenLimitMessage(e){return`The session reached its configured ${e} token limit.`}async function failSessionTokenLimit(e){let t=getSessionTokenUsage(e.session),n=formatSessionTokenLimitMessage(e.violation.kind),r={inputTokens:t.inputTokens,kind:e.violation.kind,limit:e.violation.limit,outputTokens:t.outputTokens,usedTokens:e.violation.usedTokens};return e.emit&&await emitFailedStep(e.emit,e.emissionState,{code:`SESSION_TOKEN_LIMIT_REACHED`,details:r,message:n,sessionId:e.session.sessionId}),{next:{done:!0,isError:e.config.mode===`task`?!0:void 0,output:e.config.mode===`task`?n:``},session:e.session}}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}function insertInlineToolResultMessages(e){let t=extractToolResultCallIds(e.responseMessages),n=e.prepend.filter(e=>!t.has(e.toolCallId)),r=e.append.filter(e=>!t.has(e.toolCallId));return[...n.length>0?[{role:`tool`,content:[...n]}]:[],...e.responseMessages,...r.length>0?[{role:`tool`,content:[...r]}]:[]]}function extractToolResultCallIds(e){let t=new Set;for(let n of e)if(!(n.role!==`tool`||!Array.isArray(n.content)))for(let e of n.content)e.type===`tool-result`&&t.add(e.toolCallId);return t}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}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. Answer now from the tool results above; do not re-run tools or mention this notice.`;function buildEmptyResponseNudge(e){return e?`${EMPTY_RESPONSE_NUDGE} If the current task explicitly requires conditional delivery and there is nothing to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL}.`:EMPTY_RESPONSE_NUDGE}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:buildEmptyResponseNudge(e.emptyDeliveryEnabled)})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:o,session:s}=e,c=resolveAssistantStepText(i.response.messages,i.text),l=i.finishReason!==`tool-calls`&&i.toolCalls.length===0&&hasEmptyDeliverySentinel(c),u=l?[]:i.response.messages,d=l?null:c,f=new Set;for(let e of[...i.content??[],...i.toolResults??[]])(e.type===`tool-result`||e.type===`tool-error`)&&e.providerExecuted===!0&&f.add(e.toolCallId);let p=normalizeProviderToolHistory({messages:u,providerExecutedOutcomeIds:f}),m=p.messages,h={...s,compaction:createNextCompactionConfig(s.compaction,r,i)},g=t.workflow===!0?readWorkflowContinuationSecurity(h):void 0;if(g!==void 0){let e=await getWorkflowSandboxInterrupt(i,g);if(e!==void 0){if(!isWorkflowRuntimeActionInterrupt(e))throw Error(`Unsupported Workflow interrupt kind "${e.payload.kind}".`);return parkOnWorkflowInterrupt({baseSession:h,emissionState:o,interrupt:e,promptMessages:r,responseMessages:m})}}let _=extractToolApprovalInputRequests({content:i.content??[]}),y=new Set(_.map(e=>e.action.callId)),b=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:y}),S=[..._,...b],C=getAdvertisedTools({session:h,tools:t.tools}),w=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).filter(e=>C.get(e.toolName)?.runtimeAction===void 0?(log.warn(`runtime action tool call blocked because tool is not advertised`,{callId:e.toolCallId,sessionId:h.sessionId,toolName:e.toolName}),!1):!0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:C}));if(w.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:w,event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},responseMessages:m,session:{...h,history:[...r]}}),o)};if(S.length>0){let e=setPendingInputBatch({event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},requests:S,responseMessages:m,session:{...h,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:S,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),t.mode===`conversation`&&(o=await emitTurnEpilogue(n,o,t.mode),e=setHarnessEmissionState(e,o))),{next:null,session:e}}let T=findAuthorizationSignalFromToolResults(i.toolResults);if(T){let{challenges:e}=T;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));return{next:null,session:setHarnessEmissionState({...h,history:[...r],state:setPendingAuthorization(h.state,{challenges:e})},o)}}let E=m,O=[...r,...E],k={...h,history:O};return!(k.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(E.at(-1)?.role===`tool`||p.outcomeEndsResponse||hasDeferredStepInput(k))?(n&&(o=advanceStep(o),k=setHarnessEmissionState(k,o)),{next:a,session:k}):t.mode===`task`?finishTaskTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k,stepOutput:d}):finishConversationTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,history:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,history:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingWorkflowInterrupt(e){let t=getPendingWorkflowInterrupt(e.session.state);if(t===void 0)return null;let n=t.interrupt;if(!isWorkflowRuntimeActionInterrupt(n))throw Error(`Unsupported Workflow interrupt kind "${n.payload.kind}".`);let i=e.emit===void 0?void 0:createWorkflowLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),a=getWorkflowContinuationSecurity(e.session),o;try{let t=buildWorkflowHostTools({tools:e.config.tools}),r=e.childResults??[],s=n,c=0;for(;;){o=await continueWorkflowSandboxInterrupt({continuationSecurity:a,interrupt:s,lifecycle:i,resolution:r[c]?.output,tools:t});let e=await unwrapWorkflowSandboxResult(o,a);if(e.status!==`interrupted`||!isWorkflowRuntimeActionInterrupt(e.interrupt)||c+1>=r.length)break;let n=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(n===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);c++,s=n}}catch(e){logError(log,`Workflow interrupt continuation failed`,e),o={error:`workflow_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let s=await unwrapWorkflowSandboxResult(o,a),c=s.status===`interrupted`?s.interrupt:s.output,l=replaceWorkflowToolResult([...e.session.history,...t.responseMessages],n.outerToolCallId,c),u=clearPendingWorkflowInterrupt({...e.session,history:l});if(s.status===`interrupted`){if(!isWorkflowRuntimeActionInterrupt(s.interrupt))throw Error(`Unsupported Workflow interrupt kind "${s.interrupt.payload.kind}".`);let t=e.session.history.length,n=l.slice(0,t),r=l.slice(t);return u={...u,history:n},parkOnWorkflowInterrupt({baseSession:u,emissionState:e.emissionState,interrupt:s.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:u}}function replaceWorkflowToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}function parkOnWorkflowInterrupt(e){let t=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(t===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);let n={...e.baseSession,history:[...e.promptMessages]};return{next:null,session:setHarnessEmissionState(setPendingWorkflowInterrupt({interrupt:t,responseMessages:e.responseMessages,session:n}),e.emissionState)}}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t){for(let n=1;;n++)try{return await e()}catch(e){if(n===3||classifyModelCallError(e)!==`retry`)throw e;let r=500*2**(n-1)+Math.floor(Math.random()*250);log.warn(`model call failed transiently — retrying`,{attempt:n,delayMs:r,sessionId:t.sessionId,turnId:t.turnId,error:e}),await new Promise(e=>setTimeout(e,r))}}function findAuthorizationSignalFromToolResults(e){let t=contextStorage.getStore();if(t!==void 0)for(let n of e??[]){let e=readToolInterrupt(t,n.toolCallId);if(e!==void 0&&isAuthorizationSignal(e))return e}for(let t of e??[])if(isAuthorizationSignal(t.output))return t.output}export{createToolLoopHarness};
|
|
1
|
+
import{createErrorId,createLogger,formatError,logError,recordErrorOnSpan}from"#internal/logging.js";import{isScheduleAppAuth}from"#channel/schedule-auth.js";import{AuthKey,ParentSessionKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{EmptyModelResponseError,classifyModelCallError,extractModelCallErrorDetails,extractUnsupportedProviderToolTypes,isNoOutputGeneratedError,summarizeKnownModelCallConfigError,summarizeKnownModelCallRequestError}from"#harness/model-call-error.js";import{toErrorMessage}from"#shared/errors.js";import{createActionResultEvent,createAuthorizationRequiredEvent,createCompactionCompletedEvent,createCompactionRequestedEvent,createInputRequestedEvent,createResultCompletedEvent}from"#protocol/message.js";import{formatLanguageModelGatewayId}from"#internal/runtime-model.js";import{contextStorage}from"#context/container.js";import{ToolLoopAgent,isStepCount}from"ai";import{advanceStep,emitFailedStep,emitRecoverableFailedTurn,emitStepStarted,emitStreamContent,emitTurnEpilogue,emitTurnPreamble,getHarnessEmissionState,setHarnessEmissionState}from"#harness/emission.js";import{createRuntimeActionRequestFromToolCall,resolvePendingRuntimeActions,setPendingRuntimeActionBatch}from"#harness/runtime-actions.js";import{clearPendingWorkflowInterrupt,getPendingWorkflowInterrupt,setPendingWorkflowInterrupt}from"#harness/workflow-interrupt-state.js";import{getWorkflowRuntimeActionInterrupts,isWorkflowRuntimeActionInterrupt}from"#harness/workflow-runtime-action-state.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{isAuthorizationSignal,setPendingAuthorization}from"#harness/authorization.js";import{resolveAssistantStepText}from"#harness/messages.js";import{buildDynamicInstructionMessages}from"#context/dynamic-instruction-lifecycle.js";import{PendingSkillAnnouncementKey}from"#context/dynamic-skill-lifecycle.js";import{consumeDeferredStepInput,getApprovedTools,hasDeferredStepInput,hasStepInput,resolvePendingInput,setPendingInputBatch}from"#harness/input-requests.js";import{accumulateTurnUsage,getTurnUsageState,setTurnUsageState}from"#harness/turn-tag-state.js";import{getWorkflowContinuationSecurity,readWorkflowContinuationSecurity}from"#harness/workflow-continuation-security.js";import{buildWorkflowHostTools}from"#harness/workflow-sandbox.js";import{CONDITIONAL_DELIVERY_INSTRUCTION,EMPTY_DELIVERY_SENTINEL,hasEmptyDeliverySentinel}from"#shared/empty-delivery.js";import{readToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{extractQuestionInputRequests,extractToolApprovalInputRequests}from"#harness/input-extraction.js";import{applyLastToolCacheBreakpoint,applySystemCacheBreakpoint,detectPromptCachePath,getAnthropicCacheMarker}from"#harness/prompt-cache.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{hydrateSandboxAttachments,stageAttachmentsToSandbox}from"#harness/attachment-staging.js";import{createWorkflowLifecycle}from"#harness/workflow-lifecycle.js";import{compactMessages,getInputTokenCount,resolveCompactionModel,shouldCompact}from"#harness/compaction.js";import{applySessionLimitContinuation,enforceSessionTokenLimit}from"#harness/session-limit-enforcement.js";import{setEveAttributes}from"#runtime/attributes/emit.js";import{buildTelemetryRuntimeContext}from"#harness/instrumentation-runtime-context.js";import{getInstrumentationConfig}from"#harness/instrumentation-config.js";import{normalizeProviderToolHistory}from"#harness/provider-tool-history.js";import{extractWorkflowStreamWriteErrorDetails}from"#harness/workflow-stream-error.js";import{ensureOtelIntegration}from"#harness/otel-integration.js";import{getAdvertisedTools}from"#harness/advertised-tools.js";import{resolveFrameworkToolFromUpstreamType}from"#harness/provider-tools.js";import{buildStepHooks,emitStepActions,isInvalidToolCall}from"#harness/step-hooks.js";import{buildToolApproval,buildToolSetFromDefinitions,buildToolSetWithProviderTools}from"#harness/tools.js";import{continueWorkflowSandboxInterrupt,getWorkflowSandboxInterrupt,unwrapWorkflowSandboxResult}from"#shared/workflow-sandbox.js";import{FINAL_OUTPUT_TOOL_NAME,buildFinalOutputTool}from"#runtime/framework-tools/final-output.js";const environment=process.env.NODE_ENV??`unknown`,eveVersion=resolveInstalledPackageInfo().version,log=createLogger(`harness.tool-loop`);function logToolExecutionError(e){e.toolOutput.type===`tool-error`&&logError(log,`tool execution failed`,e.toolOutput.error,{toolName:e.toolCall.toolName,toolCallId:e.toolCall.toolCallId})}function enrichTelemetry(e,t,n){if(e===void 0)return;let r={};for(let e of Object.keys(n??{}))r[e]=!0;return{functionId:e.functionId??t,includeRuntimeContext:r,isEnabled:!0,recordInputs:e.recordInputs??!0,recordOutputs:e.recordOutputs??!0}}function buildGatewayAttributionHeaders(e,t){if(typeof e!=`string`)return;let n=t?.agentName??t?.agentId,r=process.env.VERCEL_PROJECT_PRODUCTION_URL||process.env.VERCEL_URL,i=r?`https://${r}`:void 0;if(!n&&!i)return;let a={};return n&&(a[`x-title`]=n),i&&(a[`http-referer`]=i),a}const TURN_TRACE_STATE_KEY=`eve.harness.turnTrace`;function getTurnTraceState(e){return e.state?.[TURN_TRACE_STATE_KEY]}function setTurnTraceState(e,t){let n={traceId:t.traceId,spanId:t.spanId,traceFlags:t.traceFlags};return{...e,state:{...e.state,[TURN_TRACE_STATE_KEY]:n}}}function resolveStepOtelContext(e,t,n){if(t)return trace.setSpan(context.active(),t);if(e){let e=getTurnTraceState(n);if(e){let t=trace.wrapSpanContext({traceId:e.traceId,spanId:e.spanId,traceFlags:e.traceFlags});return trace.setSpan(context.active(),t)}}}function createToolLoopHarness(t){let n=t.handleEvent,c=getInstrumentationConfig();c!==void 0&&ensureOtelIntegration();let f=c===void 0?void 0:trace.getTracer(`eve`),p=t.runtimeIdentity?.agentName;async function runStep(e,t){let n;if(f&&hasStepInput(t)){let t=c?.functionId??p,r={"eve.version":eveVersion,"eve.environment":environment,"eve.session.id":e.sessionId};t&&(r[`ai.telemetry.functionId`]=t),n=f.startSpan(`ai.eve.turn`,{attributes:r})}let r=resolveStepOtelContext(f,n,e),executeStep=()=>executeStepBody(e,t,n);try{return r?await context.with(r,executeStep):await executeStep()}finally{n?.end()}}async function executeStepBody(f,v,y){let b=f;y&&(b=setTurnTraceState(b,y.spanContext()));let x=getHarnessEmissionState(b.state),S=consumeDeferredStepInput({input:v,session:b});b=S.session;let D=await resolvePendingRuntimeActions({emit:n,session:b,stepInput:S.input});if(D.outcome===`unresolved`)return{next:null,session:D.session};b=D.session;let A=resolvePendingInput({history:D.messages,resolveApprovalKey:resolveApprovalKeyFromTools(t.tools),session:b,stepInput:S.input});if(A.outcome===`unresolved`)return n&&A.deferredMessage===!0&&hasStepInput(v)?(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),x=await emitTurnEpilogue(n,x,t.mode),{next:null,session:setHarnessEmissionState(A.session,x)}):{next:null,session:A.session};if(n&&A.rejectedActions)for(let e of A.rejectedActions.results)await n(createActionResultEvent({rejected:!0,result:e,sequence:A.rejectedActions.event.sequence,stepIndex:A.rejectedActions.event.stepIndex,turnId:A.rejectedActions.event.turnId}));n&&hasStepInput(v)&&(x=await emitTurnPreamble(n,v??{},x,t.runtimeIdentity),b=setHarnessEmissionState(b,x),y&&y.setAttribute(`eve.turn.id`,x.turnId)),b=A.session;let j=A.messages,M=await applySessionLimitContinuation({config:t,emit:n,emissionState:x,limitContinuation:A.limitContinuation,session:b});if(M.result!==null)return M.result;if(b=M.session,S.input?.context!==void 0)for(let e of S.input.context)j.push({content:e,role:`user`});if(S.input?.message!==void 0&&!A.deferredMessage&&!A.consumedMessage){let e=await stageAttachmentsToSandbox(S.input.message);j.push({content:e,role:`user`})}let N=await t.resolveModel(b.agent.modelReference),P=detectPromptCachePath(N),F=P.kind===`anthropic-direct`?getAnthropicCacheMarker():void 0,I=buildGatewayAttributionHeaders(N,t.runtimeIdentity);({messages:j,session:b}=await maybeCompact({abortSignal:t.abortSignal,emit:n,emissionState:x,headers:I,messages:j,model:N,onCompaction:t.onCompaction,resolveModel:t.resolveModel,session:b,telemetry:enrichTelemetry(c,p)??void 0}));let L=getApprovedTools(b),R=contextStorage.getStore(),z=b.outputSchema===void 0&&R!==void 0&&isScheduleAppAuth(R.get(AuthKey))&&R.get(ParentSessionKey)===void 0,B=await hydrateSandboxAttachments(j),V=[],H=[];for(let e of B)e.role===`system`?V.push(e):H.push(e);if(R!==void 0){V.push(...buildDynamicInstructionMessages(R));let e=R.get(PendingSkillAnnouncementKey);e!==void 0&&e.length>0&&V.push({role:`system`,content:e})}z&&V.push({role:`system`,content:CONDITIONAL_DELIVERY_INSTRUCTION});let U=H,prepareModelCallInput=e=>{let t=e?[{role:`system`,content:e}]:[],n=b.agent.system?[{role:`system`,content:b.agent.system}]:[],r=V.length>0||t.length>0?[...t,...n,...V]:void 0,i=r!==void 0&&F?applySystemCacheBreakpoint(r,F):r??b.agent.system??void 0;return{instructions:i,telemetryRuntimeContext:buildTelemetryRuntimeContext({eveVersion,authored:c,emissionState:x,environment,modelInput:{instructions:i,messages:U},session:b})}},runOneModelCall=async e=>{let{instructions:i,telemetryRuntimeContext:a={}}=e.preparedInput??prepareModelCallInput(e.extraSystemNote);e.retryReason&&(a[`eve.retry.reason`]=e.retryReason);let o=e.trailingUserNote?[...U,{role:`user`,content:e.trailingUserNote}]:U,s=getAdvertisedTools({session:b,tools:t.tools}),u=await buildToolSetWithProviderTools({approvedTools:L,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,modelReference:b.agent.modelReference,tools:s});if(R!==void 0){let n=getAdvertisedTools({session:b,tools:buildDynamicTools(R)}),r=buildToolSetFromDefinitions({approvedTools:L,capabilities:t.capabilities,disabledProviderTools:e.disabledProviderTools,tools:n});for(let[e,t]of Object.entries(r))u[e]=t}b.outputSchema!==void 0&&(u[FINAL_OUTPUT_TOOL_NAME]=buildFinalOutputTool(b.outputSchema));let d=n===void 0?void 0:({tools:e})=>createWorkflowLifecycle({emit:n,emissionState:x,tools:e}),f=t.workflow===!0?{lifecycle:d,maxSubagents:t.workflowMaxSubagents}:void 0,h=await getAdvertisedTools({modelTools:u,session:b,tools:s,workflow:f});b=h.session;let g=h.modelTools,_=F?applyLastToolCacheBreakpoint(g,F):g,v=buildStepHooks({cachePath:P,emit:n,emissionState:x,emitStepStarted:e.suppressStepStartedEmission!==!0,marker:F,session:b}),y=new ToolLoopAgent({headers:I,instructions:i,model:N,onToolExecutionEnd:logToolExecutionError,onError(e){summarizeKnownModelCallConfigError(e.error)===null&&logError(log,`tool-loop stream error`,e.error)},onStepFinish:v.onStepFinish,prepareStep:v.prepareStep,reasoning:b.agent.reasoning,runtimeContext:a,stopWhen:isStepCount(1),telemetry:enrichTelemetry(c,p,a),toolApproval:buildToolApproval(g),tools:_}),executeModelCall=async()=>{if(n){let e=[...t.tools].filter(([e,t])=>t.runtimeAction!==void 0&&s.get(e)===void 0).map(([e])=>e),r=new Set([ASK_QUESTION_TOOL_NAME,FINAL_OUTPUT_TOOL_NAME,...e]),i=await y.stream({abortSignal:t.abortSignal,messages:o}),{emittedActionCallIds:a,handledInlineToolResultCallIds:c,inlineAuthorizationResults:u,inlineToolResultParts:d,trailingInlineToolResultParts:f}=await emitStreamContent(n,x,i.fullStream,{excludedActionToolNames:r,tools:t.tools});throwIfTurnAborted(t.abortSignal);let p=await v.stepResult;if(isEmptyModelResponse(p)&&d.length===0&&u.length===0&&f.length===0)throw new EmptyModelResponseError;if(await emitStepActions(n,x,p,{emittedActionCallIds:a,excludedActionToolNames:r,handledInlineToolResultCallIds:c,tools:s}),d.length>0||u.length>0||f.length>0){let e=p.toolResults,t=new Map(e.map(e=>[e.toolCallId,e]));for(let e of u)t.set(e.toolCallId,e);return{content:p.content,finishReason:p.finishReason,response:{...p.response,...d.length>0||f.length>0?{messages:insertInlineToolResultMessages({append:f,prepend:d,responseMessages:p.response.messages})}:{}},providerMetadata:p.providerMetadata,text:p.text,toolCalls:p.toolCalls,toolResults:[...t.values()],usage:p.usage}}return p}await y.generate({abortSignal:t.abortSignal,messages:o}),throwIfTurnAborted(t.abortSignal);let e=await v.stepResult;if(isEmptyModelResponse(e))throw new EmptyModelResponseError;return e};return runModelCallWithRetries(()=>executeModelCall().catch(rethrowNoOutputAsEmptyResponse),{sessionId:b.sessionId,turnId:x.turnId},t.abortSignal)},W=prepareModelCallInput();n&&await emitStepStarted(n,x,j);let G=await continuePendingWorkflowInterrupt({childResults:S.input?.runtimeActionResults,config:t,emit:n,emissionState:x,runStep,session:b});if(G!==null)return G;let K=await enforceSessionTokenLimit({config:t,emit:n,emissionState:x,messages:j,session:b});if(K!==null)return K;let q;try{q=await runOneModelCall({preparedInput:W,suppressStepStartedEmission:!0})}catch(r){throwIfTurnAborted(t.abortSignal);let a=await runModelCallRecoveryPipeline({error:r,stages:[e=>attemptUnsupportedProviderToolRecovery({error:e.error,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId}),e=>attemptEmptyResponseRecovery({emptyDeliveryEnabled:z,error:e.error,retryCallOptions:e.retryCallOptions,runOneModelCall,sessionId:b.sessionId,turnId:x.turnId})]});if(throwIfTurnAborted(t.abortSignal),a.outcome===`recovered`)q=a.result;else{let r=a.error;if(y&&recordErrorOnSpan(y,r),!n)throw r;let o=extractWorkflowStreamWriteErrorDetails(r);if(o!==null){let t=createErrorId();return log.error(`workflow stream write failed — parking session for retry by the user`,{...o,errorId:t,error:r,sessionId:b.sessionId,turnId:x.turnId}),x=await emitRecoverableFailedTurn(n,x,{code:`WORKFLOW_STREAM_WRITE_FAILED`,details:{...o,errorId:t},message:toErrorMessage(r)}),{next:null,session:setHarnessEmissionState(b,x)}}let s=classifyModelCallError(r),c=createErrorId(),l=s===`terminal`?summarizeKnownModelCallConfigError(r):null,f=l===null?summarizeKnownModelCallRequestError(r):null,p=l?.message??f?.message??toErrorMessage(r),_=extractModelCallErrorDetails(r),v=buildModelCallFailureDetails({configSummary:l,error:r,errorId:c,modelCallDetails:_,requestSummary:f}),S=buildModelCallFailureLogFields({error:r,errorId:c,modelCallDetails:_,requestSummary:f,sessionId:b.sessionId,turnId:x.turnId});return s===`terminal`?(l===null?log.error(f?.message??`model call failed terminally`,S):log.error(`${l.name}: ${l.message}`,{errorId:c,sessionId:b.sessionId,turnId:x.turnId}),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:t.mode===`task`?{done:!0,isError:!0,output:p}:{done:!0,output:``},session:b}):t.mode===`task`?(log.error(f?.message??`model call failed; failing the task run`,S),await emitFailedStep(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p,sessionId:b.sessionId}),{next:{done:!0,isError:!0,output:p},session:b}):(log.error(f?.message??`model call failed — parking session for retry by the user`,S),x=await emitRecoverableFailedTurn(n,x,{code:`MODEL_CALL_FAILED`,details:v,message:p}),{next:null,session:setHarnessEmissionState(b,x)})}}let J=accumulateTurnUsage({previous:getTurnUsageState(b.state),turnId:x.turnId,usage:extractTokenUsageDelta({costUsd:extractGatewayCostUsd(q.providerMetadata),usage:q.usage})});b=setTurnUsageState(b,J);let Y;try{Y=formatLanguageModelGatewayId(N)}catch{Y=void 0}return await setEveAttributes({"$eve.model":Y,"$eve.input_tokens":J.inputTokens,"$eve.output_tokens":J.outputTokens,"$eve.cache_read_tokens":J.cacheReadTokens,"$eve.cache_write_tokens":J.cacheWriteTokens,"$eve.cost_usd":J.sawCost?J.costUsd:void 0,"$eve.tool_count":t.tools.size}),handleStepResult({config:t,emit:n,emissionState:x,promptMessages:j,result:q,runStep,session:b})}return runStep}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}function buildModelCallFailureDetails(e){let{configSummary:t,error:r,errorId:i,modelCallDetails:a,requestSummary:o}=e;return t===null?o===null?{...formatError(r,i),...a}:{errorId:i,message:toErrorMessage(r),name:o.name,...a}:{errorId:i,message:t.message,name:t.name,...a}}function buildModelCallFailureLogFields(e){let t={errorId:e.errorId,sessionId:e.sessionId,turnId:e.turnId};return e.requestSummary===null?{...t,error:e.error}:{...t,details:e.modelCallDetails}}async function runModelCallRecoveryPipeline(e){let t=e.error,n;for(let r of e.stages){let e=await r({error:t,retryCallOptions:n});if(e.outcome===`recovered`)return e;e.outcome===`failed`&&(t=e.error,n=e.retryCallOptions)}return{outcome:`failed`,error:t}}function insertInlineToolResultMessages(e){let t=extractToolResultCallIds(e.responseMessages),n=e.prepend.filter(e=>!t.has(e.toolCallId)),r=e.append.filter(e=>!t.has(e.toolCallId));return[...n.length>0?[{role:`tool`,content:[...n]}]:[],...e.responseMessages,...r.length>0?[{role:`tool`,content:[...r]}]:[]]}function extractToolResultCallIds(e){let t=new Set;for(let n of e)if(!(n.role!==`tool`||!Array.isArray(n.content)))for(let e of n.content)e.type===`tool-result`&&t.add(e.toolCallId);return t}async function attemptUnsupportedProviderToolRecovery(e){let t=extractUnsupportedProviderToolTypes(e.error);if(t.length===0)return{outcome:`skipped`};let n=[];for(let e of t){let t=resolveFrameworkToolFromUpstreamType(e);t!==null&&!n.includes(t)&&n.push(t)}if(n.length===0)return{outcome:`skipped`};log.warn(`disabling unsupported provider tool(s); retrying step once`,{disabled:n,sessionId:e.sessionId,turnId:e.turnId,upstreamTypes:t});let r={disabledProviderTools:new Set(n),extraSystemNote:buildDisabledToolNote(n)};try{return{outcome:`recovered`,result:await e.runOneModelCall({...r,suppressStepStartedEmission:!0})}}catch(e){return{outcome:`failed`,error:e,retryCallOptions:r}}}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. Answer now from the tool results above; do not re-run tools or mention this notice.`;function buildEmptyResponseNudge(e){return e?`${EMPTY_RESPONSE_NUDGE} If the current task explicitly requires conditional delivery and there is nothing to report, reply with exactly ${EMPTY_DELIVERY_SENTINEL}.`:EMPTY_RESPONSE_NUDGE}async function attemptEmptyResponseRecovery(e){if(!(e.error instanceof EmptyModelResponseError))return{outcome:`skipped`};log.warn(`empty model response; reissuing the model call once`,{sessionId:e.sessionId,turnId:e.turnId});try{return{outcome:`recovered`,result:await e.runOneModelCall({...e.retryCallOptions,retryReason:`empty-response`,suppressStepStartedEmission:!0,trailingUserNote:buildEmptyResponseNudge(e.emptyDeliveryEnabled)})}}catch(t){return{outcome:`failed`,error:t,retryCallOptions:e.retryCallOptions}}}async function handleStepResult(e){let{config:t,emit:n,promptMessages:r,result:i,runStep:a}=e,{emissionState:o,session:s}=e,c=resolveAssistantStepText(i.response.messages,i.text),l=i.finishReason!==`tool-calls`&&i.toolCalls.length===0&&hasEmptyDeliverySentinel(c),u=l?[]:i.response.messages,d=l?null:c,f=new Set;for(let e of[...i.content??[],...i.toolResults??[]])(e.type===`tool-result`||e.type===`tool-error`)&&e.providerExecuted===!0&&f.add(e.toolCallId);let p=normalizeProviderToolHistory({messages:u,providerExecutedOutcomeIds:f}),m=p.messages,h={...s,compaction:createNextCompactionConfig(s.compaction,r,i)},g=t.workflow===!0?readWorkflowContinuationSecurity(h):void 0;if(g!==void 0){let e=await getWorkflowSandboxInterrupt(i,g);if(e!==void 0){if(!isWorkflowRuntimeActionInterrupt(e))throw Error(`Unsupported Workflow interrupt kind "${e.payload.kind}".`);return parkOnWorkflowInterrupt({baseSession:h,emissionState:o,interrupt:e,promptMessages:r,responseMessages:m})}}let _=extractToolApprovalInputRequests({content:i.content??[]}),y=new Set(_.map(e=>e.action.callId)),b=extractQuestionInputRequests({toolCalls:i.toolCalls,excludedCallIds:y}),S=[..._,...b],C=getAdvertisedTools({session:h,tools:t.tools}),w=(i.toolCalls??[]).filter(e=>!isInvalidToolCall(e)).filter(e=>t.tools.get(e.toolName)?.runtimeAction!==void 0).filter(e=>C.get(e.toolName)?.runtimeAction===void 0?(log.warn(`runtime action tool call blocked because tool is not advertised`,{callId:e.toolCallId,sessionId:h.sessionId,toolName:e.toolName}),!1):!0).map(e=>createRuntimeActionRequestFromToolCall({toolCall:e,tools:C}));if(w.length>0)return{next:null,session:setHarnessEmissionState(setPendingRuntimeActionBatch({actions:w,event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},responseMessages:m,session:{...h,history:[...r]}}),o)};if(S.length>0){let e=setPendingInputBatch({event:{sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId},requests:S,responseMessages:m,session:{...h,history:[...r]}});return n&&(await n(createInputRequestedEvent({requests:S,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId})),t.mode===`conversation`&&(o=await emitTurnEpilogue(n,o,t.mode),e=setHarnessEmissionState(e,o))),{next:null,session:e}}let T=findAuthorizationSignalFromToolResults(i.toolResults);if(T){let{challenges:e}=T;if(n)for(let t of e)await n(createAuthorizationRequiredEvent({authorization:t.challenge,name:t.name,description:t.challenge.instructions??`Authorization required for ${t.name}`,webhookUrl:t.hookUrl,sequence:o.sequence,stepIndex:o.stepIndex,turnId:o.turnId}));return{next:null,session:setHarnessEmissionState({...h,history:[...r],state:setPendingAuthorization(h.state,{challenges:e})},o)}}let E=m,O=[...r,...E],k={...h,history:O};return!(k.outputSchema!==void 0&&extractFinalOutput(i)!==void 0)&&(E.at(-1)?.role===`tool`||p.outcomeEndsResponse||hasDeferredStepInput(k))?(n&&(o=advanceStep(o),k=setHarnessEmissionState(k,o)),{next:a,session:k}):t.mode===`task`?finishTaskTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k,stepOutput:d}):finishConversationTurn({emissionState:o,emit:n,history:r,result:i,schema:k.outputSchema,session:k})}const OUTPUT_SCHEMA_NOT_FULFILLED={code:`OUTPUT_SCHEMA_NOT_FULFILLED`,message:`The agent could not produce a result matching the requested schema.`};function extractFinalOutput(e){return(e.toolCalls??[]).find(e=>e.toolName===FINAL_OUTPUT_TOOL_NAME)?.input}function persistStructuredAssistantTurn(e,t,n){return{...e,history:[...t,{content:JSON.stringify(n),role:`assistant`}],outputSchema:void 0}}async function emitStructuredResult(e,t,n,r){return await e(createResultCompletedEvent({result:n,sequence:t.sequence,stepIndex:t.stepIndex,turnId:t.turnId})),emitTurnEpilogue(e,t,r)}async function finishTaskTurn(e){let{emit:t,history:n,result:r,schema:i,stepOutput:a}=e,{emissionState:o,session:s}=e;if(i===void 0)return t&&(o=await emitTurnEpilogue(t,o,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:a??``},session:s};let c=extractFinalOutput(r);return c===void 0?(t&&await emitFailedStep(t,o,{...OUTPUT_SCHEMA_NOT_FULFILLED,sessionId:s.sessionId}),{next:{done:!0,isError:!0,output:OUTPUT_SCHEMA_NOT_FULFILLED.message},session:s}):(s=persistStructuredAssistantTurn(s,n,c),t&&(o=await emitStructuredResult(t,o,c,`task`),s=setHarnessEmissionState(s,o)),{next:{done:!0,output:c},session:s})}async function finishConversationTurn(e){let{emit:t,history:n,result:r,schema:i}=e,{emissionState:a,session:o}=e;if(i===void 0)return t&&(a=await emitTurnEpilogue(t,a,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o};let s=extractFinalOutput(r);return s===void 0?(t&&(a=await emitRecoverableFailedTurn(t,a,OUTPUT_SCHEMA_NOT_FULFILLED),o=setHarnessEmissionState(o,a)),{next:null,session:o}):(o=persistStructuredAssistantTurn(o,n,s),t&&(a=await emitStructuredResult(t,a,s,`conversation`),o=setHarnessEmissionState(o,a)),{next:null,session:o})}async function continuePendingWorkflowInterrupt(e){let t=getPendingWorkflowInterrupt(e.session.state);if(t===void 0)return null;let n=t.interrupt;if(!isWorkflowRuntimeActionInterrupt(n))throw Error(`Unsupported Workflow interrupt kind "${n.payload.kind}".`);let i=e.emit===void 0?void 0:createWorkflowLifecycle({emit:e.emit,emissionState:e.emissionState,skipReplayed:!0,tools:e.config.tools}),a=getWorkflowContinuationSecurity(e.session),o;try{let t=buildWorkflowHostTools({tools:e.config.tools}),r=e.childResults??[],s=n,c=0;for(;;){o=await continueWorkflowSandboxInterrupt({continuationSecurity:a,interrupt:s,lifecycle:i,resolution:r[c]?.output,tools:t});let e=await unwrapWorkflowSandboxResult(o,a);if(e.status!==`interrupted`||!isWorkflowRuntimeActionInterrupt(e.interrupt)||c+1>=r.length)break;let n=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(n===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);c++,s=n}}catch(e){logError(log,`Workflow interrupt continuation failed`,e),o={error:`workflow_continuation_failed`,message:toErrorMessage(e),retryable:!1}}let s=await unwrapWorkflowSandboxResult(o,a),c=s.status===`interrupted`?s.interrupt:s.output,l=replaceWorkflowToolResult([...e.session.history,...t.responseMessages],n.outerToolCallId,c),u=clearPendingWorkflowInterrupt({...e.session,history:l});if(s.status===`interrupted`){if(!isWorkflowRuntimeActionInterrupt(s.interrupt))throw Error(`Unsupported Workflow interrupt kind "${s.interrupt.payload.kind}".`);let t=e.session.history.length,n=l.slice(0,t),r=l.slice(t);return u={...u,history:n},parkOnWorkflowInterrupt({baseSession:u,emissionState:e.emissionState,interrupt:s.interrupt,promptMessages:n,responseMessages:r})}return{next:e.runStep,session:u}}function replaceWorkflowToolResult(e,t,n){if(t===void 0)return[...e];let r=typeof n==`string`?{type:`text`,value:n}:{type:`json`,value:n};return e.map(e=>{if(e.role!==`tool`)return e;let n=e.content.map(e=>e.type!==`tool-result`||e.toolCallId!==t?e:{...e,output:r});return{...e,content:n}})}function parkOnWorkflowInterrupt(e){let t=getWorkflowRuntimeActionInterrupts(e.interrupt)[0];if(t===void 0)throw Error(`Workflow continuation contains no pending runtime-action interrupt.`);let n={...e.baseSession,history:[...e.promptMessages]};return{next:null,session:setHarnessEmissionState(setPendingWorkflowInterrupt({interrupt:t,responseMessages:e.responseMessages,session:n}),e.emissionState)}}function createNextCompactionConfig(e,t,n){let r={recentWindowSize:e.recentWindowSize,threshold:e.threshold};return n.usage?.inputTokens!==void 0&&(r.lastKnownInputTokens=n.usage.inputTokens,r.lastKnownPromptMessageCount=t.length),r}async function maybeCompact(e){let{emit:t,emissionState:n}=e,r=e.messages,i=e.session;if(!shouldCompact(r,i.compaction))return{messages:r,session:i};let a=await resolveCompactionModel({compactionModelReference:i.agent.compactionModelReference,model:e.model,modelReference:i.agent.modelReference,resolveModel:e.resolveModel});if(t&&await t(createCompactionRequestedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId,usageInputTokens:getInputTokenCount(r,i.compaction)})),r=await compactMessages(r,a.model,i.compaction,a.providerOptions,e.telemetry,e.headers,e.abortSignal),e.onCompaction)for(let t of e.onCompaction())r.push(t);return t&&await t(createCompactionCompletedEvent({modelId:formatLanguageModelGatewayId(a.model),sequence:n.sequence,sessionId:i.sessionId,turnId:n.turnId})),{messages:r,session:i}}function resolveApprovalKeyFromTools(e){return t=>{let n=e.get(t.action.toolName);if(n?.approvalKey!==void 0)return n.approvalKey(t.action.input)}}async function runModelCallWithRetries(e,t,n){for(let r=1;;r++){throwIfTurnAborted(n);try{return await e()}catch(e){if(throwIfTurnAborted(n),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 new Promise(e=>setTimeout(e,i))}}}function findAuthorizationSignalFromToolResults(e){let t=contextStorage.getStore();if(t!==void 0)for(let n of e??[]){let e=readToolInterrupt(t,n.toolCallId);if(e!==void 0&&isAuthorizationSignal(e))return e}for(let t of e??[])if(isAuthorizationSignal(t.output))return t.output}export{createToolLoopHarness};
|
|
@@ -3,6 +3,7 @@ import type { SessionCapabilities } from "#channel/types.js";
|
|
|
3
3
|
import type { RuntimeModelReference } from "#runtime/agent/bootstrap.js";
|
|
4
4
|
import type { HarnessToolDefinition } from "#harness/execute-tool.js";
|
|
5
5
|
import type { HarnessToolMap } from "#harness/types.js";
|
|
6
|
+
import type { ToolExecuteOptions } from "#shared/tool-definition.js";
|
|
6
7
|
/**
|
|
7
8
|
* Builds an AI SDK `ToolSet` from unified harness tool definitions.
|
|
8
9
|
*
|
|
@@ -44,9 +45,7 @@ export declare function buildToolSetFromDefinitions(input: {
|
|
|
44
45
|
* omits OAuth URLs, user codes, and hook URLs from model-facing history.
|
|
45
46
|
* Returns `undefined` for client-side tools (no `execute`).
|
|
46
47
|
*/
|
|
47
|
-
export declare function wrapToolExecute(definition: HarnessToolDefinition): ((input: any, options:
|
|
48
|
-
readonly toolCallId: string;
|
|
49
|
-
}) => Promise<any>) | undefined;
|
|
48
|
+
export declare function wrapToolExecute(definition: HarnessToolDefinition): ((input: any, options: ToolExecuteOptions) => Promise<any>) | undefined;
|
|
50
49
|
/**
|
|
51
50
|
* Builds the AI SDK ToolSet for one harness step.
|
|
52
51
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isObject}from"#shared/guards.js";import{parseJsonValue}from"#shared/json.js";import{loadContext}from"#context/container.js";import{
|
|
1
|
+
import{isObject}from"#shared/guards.js";import{parseJsonValue}from"#shared/json.js";import{loadContext}from"#context/container.js";import{buildCallbackContext}from"#context/build-callback-context.js";import{tool}from"ai";import{authorizationPendingModelText,isAuthorizationPendingModelOutput,isAuthorizationSignal,modelFacingAuthorizationOutput}from"#harness/authorization.js";import{withToolOutputSerializationError}from"#harness/tool-output-serialization.js";import{stashToolInterrupt}from"#harness/tool-interrupts.js";import{ASK_QUESTION_TOOL_NAME}from"#runtime/framework-tools/ask-question.js";import{WEB_SEARCH_TOOL_DEFINITION}from"#runtime/framework-tools/web-search.js";import{resolveWebSearchBackend,resolveWebSearchProviderTool}from"#harness/provider-tools.js";const toolApprovals=new WeakMap;function buildToolSet(e){let t={},n=e.capabilities?.requestInput===!0,r=e.disabledProviderTools;for(let s of e.tools.values()){if(s.name===ASK_QUESTION_TOOL_NAME&&!n||r?.has(s.name))continue;let c=s.toModelOutput,l=buildApprovalFn(s,e),u=tool({description:s.description,execute:wrapToolExecute(s),inputSchema:s.inputSchema,outputSchema:s.outputSchema,...s.execute===void 0?c===void 0?{}:{toModelOutput:async({output:e,toolCallId:t})=>normalizeToolModelOutput({output:await c(e),toolCallId:t,toolName:s.name})}:{toModelOutput:async({output:e,toolCallId:t})=>isAuthorizationPendingModelOutput(e)?{type:`text`,value:authorizationPendingModelText(e.connections)}:c===void 0?typeof e==`string`?{type:`text`,value:e}:normalizeToolModelOutput({output:{type:`json`,value:e??null},toolCallId:t,toolName:s.name}):normalizeToolModelOutput({output:await c(e),toolCallId:t,toolName:s.name})}});t[s.name]=u,s.approval!==void 0&&toolApprovals.set(u,l)}return t}function buildToolSetFromDefinitions(e){let t=new Map;for(let n of e.tools)t.has(n.name)||t.set(n.name,n);return buildToolSet({approvedTools:e.approvedTools,capabilities:e.capabilities,disabledProviderTools:e.disabledProviderTools,tools:t})}function wrapToolExecute(e){let t=e.execute;if(t!==void 0)return async(r,i)=>{let a=await t(r,i);return isAuthorizationSignal(a)?(stashToolInterrupt(loadContext(),i.toolCallId,a),modelFacingAuthorizationOutput(a)):normalizeToolJsonOutput({boundary:`execute`,output:a,toolCallId:i.toolCallId,toolName:e.name})}}function normalizeToolJsonOutput(e){let n=e.output===void 0?null:e.output;return withToolOutputSerializationError(e,()=>(parseJsonValue(n),n))}function normalizeToolModelOutput(e){return withToolOutputSerializationError({boundary:`toModelOutput`,toolCallId:e.toolCallId,toolName:e.toolName},()=>{if(e.output===null||typeof e.output!=`object`)throw TypeError(`Expected a tool model output object.`);let t=e.output;if(t.type===`text`){if(typeof t.value!=`string`)throw TypeError(`Expected text model output to include a string "value".`);return{type:`text`,value:t.value}}if(t.type===`json`)return{type:`json`,value:normalizeToolJsonOutput({boundary:`toModelOutput`,output:t.value,toolCallId:e.toolCallId,toolName:e.toolName})};throw TypeError(`Expected tool model output type to be "text" or "json".`)})}async function buildToolSetWithProviderTools(e){let t=e.disabledProviderTools,n={...buildToolSet({approvedTools:e.approvedTools,capabilities:e.capabilities,disabledProviderTools:t,tools:e.tools})};if(!t?.has(WEB_SEARCH_TOOL_DEFINITION.name)){let t=e.tools.get(WEB_SEARCH_TOOL_DEFINITION.name);if(t!==void 0&&t.execute===void 0){let t=resolveWebSearchBackend(e.modelReference);t===null?delete n[WEB_SEARCH_TOOL_DEFINITION.name]:n[WEB_SEARCH_TOOL_DEFINITION.name]=await resolveWebSearchProviderTool(t)}}return n}function buildApprovalFn(t,n){return async(i,a)=>{if(t.approval===void 0)return;let o=isObject(i)?i:void 0,s=await t.approval({...buildCallbackContext(),approvedTools:n.approvedTools??new Set,callId:a,toolInput:o,toolName:t.name});return typeof s==`boolean`?s?`user-approval`:`not-applicable`:s}}function buildToolApproval(e){return async({toolCall:t})=>{let n=e[t.toolName];return n===void 0?void 0:await toolApprovals.get(n)?.(t.input,t.toolCallId)}}export{buildToolApproval,buildToolSet,buildToolSetFromDefinitions,buildToolSetWithProviderTools,wrapToolExecute};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Terminal outcome of a cancelled turn. */
|
|
2
|
+
export declare class TurnCancelledError extends Error {
|
|
3
|
+
constructor(message?: string);
|
|
4
|
+
}
|
|
5
|
+
/** True when the error, or one of its causes, is a {@link TurnCancelledError}. */
|
|
6
|
+
export declare function isTurnCancellation(error: unknown): boolean;
|
|
7
|
+
/** Throws when the turn signal has aborted. */
|
|
8
|
+
export declare function throwIfTurnAborted(abortSignal: AbortSignal | undefined): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const TURN_CANCELLED_ERROR_NAME=`TurnCancelledError`;var TurnCancelledError=class extends Error{constructor(t=`The turn was cancelled.`){super(t),this.name=TURN_CANCELLED_ERROR_NAME}};function isTurnCancellation(t){let n=t,r=new Set;for(;typeof n==`object`&&n&&!r.has(n);){if(r.add(n),n.name===TURN_CANCELLED_ERROR_NAME)return!0;n=n.cause}return!1}function throwIfTurnAborted(e){if(e?.aborted===!0)throw isTurnCancellation(e.reason)?e.reason:new TurnCancelledError}export{TurnCancelledError,isTurnCancellation,throwIfTurnAborted};
|
|
@@ -14,13 +14,23 @@
|
|
|
14
14
|
* `turnId` keys the turn totals so a fresh turn starts at zero without relying
|
|
15
15
|
* on a separate "reset" code path. Session totals stay in the same state record
|
|
16
16
|
* and keep accumulating until the durable session ends.
|
|
17
|
+
*
|
|
18
|
+
* `TokenUsageTotals` carries `costUsd`/`sawCost` alongside the token counts
|
|
19
|
+
* for the `$eve.*` dashboard tags and session limits — fields the
|
|
20
|
+
* cross-cutting {@link TokenUsage} contract (subagent results, callback
|
|
21
|
+
* bodies, usage spans) does not carry. {@link toUsage} projects a total down
|
|
22
|
+
* to that shared shape at the one site (the driver's `done` action) where a
|
|
23
|
+
* session total crosses into it.
|
|
17
24
|
*/
|
|
18
25
|
import type { HarnessSession, SessionStateMap } from "#harness/types.js";
|
|
26
|
+
import type { TokenUsage } from "#shared/token-usage.js";
|
|
19
27
|
export interface TokenUsageTotals {
|
|
20
28
|
readonly cacheReadTokens: number;
|
|
21
29
|
readonly cacheWriteTokens: number;
|
|
30
|
+
readonly costUsd: number;
|
|
22
31
|
readonly inputTokens: number;
|
|
23
32
|
readonly outputTokens: number;
|
|
33
|
+
readonly sawCost: boolean;
|
|
24
34
|
}
|
|
25
35
|
export type TokenUsageDelta = Partial<TokenUsageTotals>;
|
|
26
36
|
/**
|
|
@@ -46,6 +56,18 @@ export type SessionTokenLimitViolation = {
|
|
|
46
56
|
readonly usedTokens: number;
|
|
47
57
|
};
|
|
48
58
|
export declare function getSessionTokenUsage(session: Pick<HarnessSession, "state">): TokenUsageTotals;
|
|
59
|
+
/** Projects a {@link TokenUsageTotals} down to the cross-cutting {@link TokenUsage} shape. */
|
|
60
|
+
export declare function toUsage(totals: TokenUsageTotals): TokenUsage;
|
|
61
|
+
/**
|
|
62
|
+
* Resets the session token budget windows to the current usage totals.
|
|
63
|
+
*
|
|
64
|
+
* Called when the user grants a continuation after a session token limit was
|
|
65
|
+
* reached. The configured limits keep their values and act as the size of the
|
|
66
|
+
* next budget window, measured from the moment of the grant. Both windows
|
|
67
|
+
* reset together so a session near two limits gets one prompt, not two
|
|
68
|
+
* back-to-back.
|
|
69
|
+
*/
|
|
70
|
+
export declare function extendSessionTokenBudget(session: HarnessSession): HarnessSession;
|
|
49
71
|
export declare function getSessionTokenLimitViolation(session: Pick<HarnessSession, "limits" | "state">): SessionTokenLimitViolation | null;
|
|
50
72
|
/** Writes per-turn token state onto a new copy of the session. */
|
|
51
73
|
export declare function setTurnUsageState(session: HarnessSession, next: TurnUsageState): HarnessSession;
|
|
@@ -60,3 +82,14 @@ export declare function accumulateTurnUsage(input: {
|
|
|
60
82
|
readonly turnId: string;
|
|
61
83
|
readonly usage: TokenUsageDelta | undefined;
|
|
62
84
|
}): TurnUsageState;
|
|
85
|
+
/**
|
|
86
|
+
* Folds a delegated child session's reported totals into the parent's
|
|
87
|
+
* session totals without touching the in-flight turn totals. Turn tags
|
|
88
|
+
* attribute only the parent's own model calls (child spend is attributed by
|
|
89
|
+
* the caller-side `invoke_agent` span); session totals feed the session
|
|
90
|
+
* token limits and the remaining-quota budget granted to later delegations.
|
|
91
|
+
*/
|
|
92
|
+
export declare function accumulateSessionUsage(input: {
|
|
93
|
+
readonly previous: TurnUsageState | undefined;
|
|
94
|
+
readonly usage: TokenUsageDelta;
|
|
95
|
+
}): TurnUsageState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const HARNESS_TURN_USAGE_STATE_KEY=`eve.harness.turnUsage`,ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,inputTokens:0,outputTokens:0};function getTurnUsageState(t){return t?.[HARNESS_TURN_USAGE_STATE_KEY]}function getSessionTokenUsage(e){return getTurnUsageState(e.state)?.session??ZERO_TOKEN_USAGE}function getSessionTokenLimitViolation(e){let t=getSessionTokenUsage(e),n=e.limits?.maxInputTokensPerSession,
|
|
1
|
+
const HARNESS_TURN_USAGE_STATE_KEY=`eve.harness.turnUsage`,SESSION_TOKEN_BUDGET_BASELINE_KEY=`eve.harness.sessionTokenBudgetBaseline`,ZERO_TOKEN_USAGE={cacheReadTokens:0,cacheWriteTokens:0,costUsd:0,inputTokens:0,outputTokens:0,sawCost:!1};function getTurnUsageState(t){return t?.[HARNESS_TURN_USAGE_STATE_KEY]}function getSessionTokenUsage(e){return getTurnUsageState(e.state)?.session??ZERO_TOKEN_USAGE}function toUsage(e){return{cacheReadTokens:e.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens,inputTokens:e.inputTokens,outputTokens:e.outputTokens}}const ZERO_BUDGET_BASELINE={inputTokens:0,outputTokens:0};function getSessionTokenBudgetBaseline(e){return e?.[SESSION_TOKEN_BUDGET_BASELINE_KEY]??ZERO_BUDGET_BASELINE}function extendSessionTokenBudget(e){let n=getSessionTokenUsage(e);return{...e,state:{...e.state,[SESSION_TOKEN_BUDGET_BASELINE_KEY]:{inputTokens:n.inputTokens,outputTokens:n.outputTokens}}}}function getSessionTokenLimitViolation(e){let t=getSessionTokenUsage(e),n=getSessionTokenBudgetBaseline(e.state),r=e.limits?.maxInputTokensPerSession,i=e.limits?.maxOutputTokensPerSession,a=t.inputTokens-n.inputTokens,o=t.outputTokens-n.outputTokens;return r!==void 0&&a>=r?{kind:`input`,limit:r,usedTokens:a}:i!==void 0&&o>=i?{kind:`output`,limit:i,usedTokens:o}:null}function setTurnUsageState(t,n){return{...t,state:{...t.state,[HARNESS_TURN_USAGE_STATE_KEY]:n}}}function accumulateTurnUsage(e){let t=toTokenUsageDelta(e.usage),r=e.previous?.session??ZERO_TOKEN_USAGE;return{...addTokenUsage(e.previous!==void 0&&e.previous.turnId===e.turnId?e.previous:ZERO_TOKEN_USAGE,t),turnId:e.turnId,session:addTokenUsage(r,t)}}function accumulateSessionUsage(e){let t=toTokenUsageDelta(e.usage),r=e.previous??{...ZERO_TOKEN_USAGE,session:ZERO_TOKEN_USAGE,turnId:``};return{...r,session:addTokenUsage(r.session,t)}}function addTokenUsage(e,t){return{cacheReadTokens:e.cacheReadTokens+t.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens+t.cacheWriteTokens,costUsd:e.costUsd+t.costUsd,inputTokens:e.inputTokens+t.inputTokens,outputTokens:e.outputTokens+t.outputTokens,sawCost:e.sawCost||t.sawCost}}function toTokenUsageDelta(e){if(e===void 0)return ZERO_TOKEN_USAGE;let t=e.inputTokens??0,r=e.outputTokens??0;return{cacheReadTokens:e.cacheReadTokens??0,cacheWriteTokens:e.cacheWriteTokens??0,costUsd:e.costUsd??0,inputTokens:t,outputTokens:r,sawCost:e.costUsd!==void 0}}export{accumulateSessionUsage,accumulateTurnUsage,extendSessionTokenBudget,getSessionTokenLimitViolation,getSessionTokenUsage,getTurnUsageState,setTurnUsageState,toUsage};
|
|
@@ -79,15 +79,24 @@ export interface HarnessSession {
|
|
|
79
79
|
* harness uses the framework default.
|
|
80
80
|
*/
|
|
81
81
|
readonly subagentMaxDepth?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Effective maximum subagent calls one `Workflow` invocation may dispatch
|
|
84
|
+
* for this session. Resolved at session creation as the tighter of the
|
|
85
|
+
* agent's `limits.maxSubagents` and any cap inherited from the parent run.
|
|
86
|
+
* When omitted, the dispatch step applies the framework default.
|
|
87
|
+
*/
|
|
88
|
+
readonly workflowMaxSubagents?: number;
|
|
82
89
|
}
|
|
83
90
|
/**
|
|
84
91
|
* Token limits stored on one durable session.
|
|
85
92
|
*/
|
|
86
93
|
export interface SessionLimits {
|
|
87
94
|
/**
|
|
88
|
-
* Maximum provider-reported input tokens this durable session may spend
|
|
89
|
-
* eve refuses to start another model call.
|
|
90
|
-
*
|
|
95
|
+
* Maximum provider-reported input tokens this durable session may spend
|
|
96
|
+
* before eve refuses to start another model call. Absent when the session
|
|
97
|
+
* is uncapped. Root sessions default to 40M unless authored otherwise;
|
|
98
|
+
* delegated subagent sessions receive the parent's remaining quota at
|
|
99
|
+
* dispatch time.
|
|
91
100
|
*/
|
|
92
101
|
readonly maxInputTokensPerSession?: number;
|
|
93
102
|
/**
|
|
@@ -189,6 +198,8 @@ export type HandleEventFn = (event: HandleMessageStreamEvent, messages?: readonl
|
|
|
189
198
|
* Dependencies injected into the tool-loop harness at construction time.
|
|
190
199
|
*/
|
|
191
200
|
export interface ToolLoopHarnessConfig {
|
|
201
|
+
/** Cancellation signal for the active turn. */
|
|
202
|
+
readonly abortSignal?: AbortSignal;
|
|
192
203
|
/**
|
|
193
204
|
* Session-level capabilities. The harness reads
|
|
194
205
|
* {@link SessionCapabilities.requestInput} when assembling the
|
|
@@ -199,10 +210,18 @@ export interface ToolLoopHarnessConfig {
|
|
|
199
210
|
* Exposes the `Workflow` orchestration tool — an isolated JavaScript sandbox
|
|
200
211
|
* whose only callable operations are this agent's subagents and remote
|
|
201
212
|
* agents. Resolved by the runtime from the agent's `workflowEnabled` flag
|
|
202
|
-
*
|
|
213
|
+
* (set when `agent/tools/workflow.ts` re-exports the `ExperimentalWorkflow`
|
|
214
|
+
* marker). Only root sessions ever see the tool.
|
|
203
215
|
* Defaults to `false`.
|
|
204
216
|
*/
|
|
205
217
|
readonly workflow?: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Maximum subagent calls one `Workflow` invocation may dispatch, from the
|
|
220
|
+
* agent's `limits.maxSubagents`. Advertised in the tool description; the
|
|
221
|
+
* dispatch step enforces it. Defaults to
|
|
222
|
+
* {@link import("#harness/workflow-subagent-limit.js").DEFAULT_WORKFLOW_MAX_SUBAGENTS}.
|
|
223
|
+
*/
|
|
224
|
+
readonly workflowMaxSubagents?: number;
|
|
206
225
|
readonly handleEvent?: HandleEventFn;
|
|
207
226
|
/**
|
|
208
227
|
* Execution mode for the current harness.
|
|
@@ -13,6 +13,7 @@ export declare function applyWorkflowTool(input: {
|
|
|
13
13
|
readonly continuationSecurity: WorkflowSandboxContinuationSecurity;
|
|
14
14
|
readonly harnessTools: HarnessToolMap;
|
|
15
15
|
readonly lifecycle?: WorkflowSandboxLifecycle;
|
|
16
|
+
readonly maxSubagents?: number;
|
|
16
17
|
readonly tools: ToolSet;
|
|
17
18
|
}): Promise<WorkflowToolSet>;
|
|
18
19
|
/** Rebuilds the subagent-only host surface used to resume a parked workflow. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsonSchema}from"ai";import{WORKFLOW_RUNTIME_ACTION_INTERRUPT_KIND}from"#harness/workflow-runtime-action-state.js";import{WORKFLOW_TOOL_NAME,createWorkflowSandboxTool,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt}from"#shared/workflow-sandbox.js";import{workflowToolDescription}from"#harness/workflow-tool-description.js";async function applyWorkflowTool(t){let i=createWorkflowHostTools(t.harnessTools,Object.keys(t.tools));if(Object.keys(i).length===0)return{hostTools:i,modelTools:t.tools};let a=await createWorkflowSandboxTool({continuationSecurity:t.continuationSecurity,hostTools:i,lifecycle:t.lifecycle}),s=typeof a.description==`string`?a.description:``,c=workflowToolDescription(Object.keys(i)),l=workflowApiReference(s),u={...t.tools};return u[WORKFLOW_TOOL_NAME]={...a,description:l.length>0?`${c}\n\n${l}`:c,inputSchema:jsonSchema({type:`object`,properties:{js:{type:`string`,description:`Complete JavaScript orchestration program. Call only the agents listed in the Workflow description and return one JSON-serializable result.`}},required:[`js`],additionalProperties:!1})},{hostTools:i,modelTools:u}}function workflowApiReference(e){let t=e.indexOf(`Tools:
|
|
1
|
+
import{jsonSchema}from"ai";import{WORKFLOW_RUNTIME_ACTION_INTERRUPT_KIND}from"#harness/workflow-runtime-action-state.js";import{WORKFLOW_TOOL_NAME,createWorkflowSandboxTool,readWorkflowSandboxResolution,requestWorkflowSandboxInterrupt}from"#shared/workflow-sandbox.js";import{workflowToolDescription}from"#harness/workflow-tool-description.js";async function applyWorkflowTool(t){let i=createWorkflowHostTools(t.harnessTools,Object.keys(t.tools));if(Object.keys(i).length===0)return{hostTools:i,modelTools:t.tools};let a=await createWorkflowSandboxTool({continuationSecurity:t.continuationSecurity,hostTools:i,lifecycle:t.lifecycle}),s=typeof a.description==`string`?a.description:``,c=workflowToolDescription(Object.keys(i),{maxSubagents:t.maxSubagents}),l=workflowApiReference(s),u={...t.tools};return u[WORKFLOW_TOOL_NAME]={...a,description:l.length>0?`${c}\n\n${l}`:c,inputSchema:jsonSchema({type:`object`,properties:{js:{type:`string`,description:`Complete JavaScript orchestration program. Call only the agents listed in the Workflow description and return one JSON-serializable result.`}},required:[`js`],additionalProperties:!1})},{hostTools:i,modelTools:u}}function workflowApiReference(e){let t=e.indexOf(`Tools:
|
|
2
2
|
`);return t<0?e:`Available agent API:\n${e.slice(t+7)}`}function buildWorkflowHostTools(e){return createWorkflowHostTools(e.tools,e.tools.keys())}function createWorkflowHostTools(e,t){let n={};for(let r of t){let t=e.get(r);t?.runtimeAction!==void 0&&(n[r]=createWorkflowRuntimeActionHostTool(t))}return n}function createWorkflowRuntimeActionHostTool(e){return{description:e.description,inputSchema:e.inputSchema,execute:async(n,r)=>{let o=readWorkflowSandboxResolution(r);return o===void 0?requestWorkflowSandboxInterrupt({kind:WORKFLOW_RUNTIME_ACTION_INTERRUPT_KIND,runtimeAction:e.runtimeAction,toolInput:n,toolName:e.name}):o}}}export{applyWorkflowTool,buildWorkflowHostTools};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RuntimeActionRequest } from "#runtime/actions/types.js";
|
|
2
|
+
import type { WorkflowSandboxInterrupt } from "#shared/workflow-sandbox.js";
|
|
3
|
+
/**
|
|
4
|
+
* Default for `limits.maxSubagents`: the maximum number of subagent (and
|
|
5
|
+
* remote-agent) calls one `Workflow` tool invocation may dispatch.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_WORKFLOW_MAX_SUBAGENTS = 100;
|
|
8
|
+
/**
|
|
9
|
+
* Partition of one workflow interrupt's pending runtime actions against the
|
|
10
|
+
* invocation's subagent budget. `allowed` actions may dispatch; `blocked`
|
|
11
|
+
* actions must resolve with an error result instead of starting a child.
|
|
12
|
+
*/
|
|
13
|
+
export type WorkflowSubagentDispatchPlan = {
|
|
14
|
+
readonly allowed: readonly RuntimeActionRequest[];
|
|
15
|
+
readonly blocked: readonly RuntimeActionRequest[];
|
|
16
|
+
readonly maxSubagents: number;
|
|
17
|
+
readonly usedCalls: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Counts the subagent calls this Workflow invocation has already resolved.
|
|
21
|
+
*
|
|
22
|
+
* Every host tool bridged into the workflow sandbox is a subagent or
|
|
23
|
+
* remote-agent call, so each fulfilled or rejected `tool` ledger entry is one
|
|
24
|
+
* consumed call. Entries still `interrupted` are the pending actions being
|
|
25
|
+
* planned, not consumed budget.
|
|
26
|
+
*/
|
|
27
|
+
export declare function countResolvedWorkflowSubagentCalls(interrupt: WorkflowSandboxInterrupt): number;
|
|
28
|
+
/**
|
|
29
|
+
* Splits the pending actions of one workflow interrupt into the prefix that
|
|
30
|
+
* still fits the invocation's `maxSubagents` budget and the remainder that
|
|
31
|
+
* must be blocked. Actions keep ledger order so results pair with the
|
|
32
|
+
* sandbox program's call order.
|
|
33
|
+
*/
|
|
34
|
+
export declare function planWorkflowSubagentDispatch(input: {
|
|
35
|
+
readonly actions: readonly RuntimeActionRequest[];
|
|
36
|
+
readonly interrupt: WorkflowSandboxInterrupt;
|
|
37
|
+
readonly maxSubagents?: number;
|
|
38
|
+
}): WorkflowSubagentDispatchPlan;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const DEFAULT_WORKFLOW_MAX_SUBAGENTS=100;function countResolvedWorkflowSubagentCalls(e){let t=0;for(let n of e.continuation.ledger)n.kind===`tool`&&n.status!==`interrupted`&&(t+=1);return t}function planWorkflowSubagentDispatch(e){let t=e.maxSubagents??100,n=countResolvedWorkflowSubagentCalls(e.interrupt),r=Math.max(0,t-n);return{allowed:e.actions.slice(0,r),blocked:e.actions.slice(r),maxSubagents:t,usedCalls:n}}export{DEFAULT_WORKFLOW_MAX_SUBAGENTS,countResolvedWorkflowSubagentCalls,planWorkflowSubagentDispatch};
|
|
@@ -13,5 +13,10 @@
|
|
|
13
13
|
* framing.
|
|
14
14
|
*
|
|
15
15
|
* @param toolNames - Names of the agent functions callable inside the sandbox.
|
|
16
|
+
* @param options - `maxSubagents`: the invocation's subagent-call budget
|
|
17
|
+
* (defaults to {@link DEFAULT_WORKFLOW_MAX_SUBAGENTS}), surfaced so the
|
|
18
|
+
* model sizes its fan-out to fit.
|
|
16
19
|
*/
|
|
17
|
-
export declare function workflowToolDescription(toolNames: readonly string[]
|
|
20
|
+
export declare function workflowToolDescription(toolNames: readonly string[], options?: {
|
|
21
|
+
readonly maxSubagents?: number;
|
|
22
|
+
}): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function workflowToolDescription(
|
|
1
|
+
import{DEFAULT_WORKFLOW_MAX_SUBAGENTS}from"#harness/workflow-subagent-limit.js";function workflowToolDescription(t,n){let r=n?.maxSubagents??DEFAULT_WORKFLOW_MAX_SUBAGENTS,i=t.length>0?t:[`agent`],a=i.map(e=>`\`${e}\``).join(`, `),o=i.filter(e=>e!==`agent`),s=o.length>0?`\n\nDeclared subagents use the same API — e.g. \`const note = await ${agentAccess(o[0])}({ message: "..." });\`.`:``;return`Use \`Workflow\` when a task needs JavaScript to coordinate multiple child-agent calls as one durable step. It is an orchestration tool, not a general-purpose tool runner.
|
|
2
2
|
|
|
3
3
|
Use \`Workflow\` for:
|
|
4
4
|
- fan-out or map-reduce over a list, especially when the number of calls comes from runtime data;
|
|
@@ -14,7 +14,9 @@ Do not use \`Workflow\` when:
|
|
|
14
14
|
|
|
15
15
|
Workflow earns its overhead when code materially controls call count, concurrency, ordering, data flow, or aggregation. Put the complete orchestration in one JavaScript program and return the final JSON-serializable value.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
One Workflow program may dispatch at most ${String(r)} agent calls in total (sequential and parallel calls alike); calls beyond that budget fail with \`WORKFLOW_SUBAGENT_LIMIT_REACHED\` instead of running. Size fan-outs to fit the budget.
|
|
18
|
+
|
|
19
|
+
The only callable operations are these agents — no filesystem, network, shell, or other tools: ${a}. Call them only through the \`tools\` object, using the exact member syntax in the API reference below. Each call is async and resolves to the child's result, or a typed object when you pass an \`outputSchema\`. Sequence with \`await\`, run agents concurrently with \`Promise.all([...])\`, and use \`map\`/\`filter\`/\`flatMap\` to build calls and combine results. The program's return value becomes the tool result.
|
|
18
20
|
|
|
19
21
|
Example — fan out across areas with \`agent\`, then pipe the results into a synthesis step:
|
|
20
22
|
\`\`\`js
|
|
@@ -32,4 +34,4 @@ const verdict = await tools.agent({
|
|
|
32
34
|
outputSchema: { type: "object", properties: { verdict: { type: "string" }, blocking: { type: "boolean" } } },
|
|
33
35
|
});
|
|
34
36
|
return verdict;
|
|
35
|
-
\`\`\`${
|
|
37
|
+
\`\`\`${s}`}function agentAccess(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/u.test(e)?`tools.${e}`:`tools[${JSON.stringify(e)}]`}export{workflowToolDescription};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.
|
|
1
|
+
import{createRequire}from"node:module";import{existsSync,readFileSync,realpathSync}from"node:fs";import{basename,dirname,join}from"node:path";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{fileURLToPath}from"node:url";let cachedPackageInfo;const BUNDLED_FALLBACK_PACKAGE_VERSION=`0.21.0`,WORKFLOW_MODULE_ALIASES={"workflow/errors":`src/compiled/@workflow/errors/index.js`,"workflow/internal/private":`src/compiled/@workflow/core/private.js`};function resolveFallbackPackageVersion(){return BUNDLED_FALLBACK_PACKAGE_VERSION.startsWith(`__`)?`0.0.0`:BUNDLED_FALLBACK_PACKAGE_VERSION}const FALLBACK_PACKAGE_INFO={name:EVE_PACKAGE_NAME,version:resolveFallbackPackageVersion()};function resolveCurrentModulePath(){return typeof __filename==`string`?__filename:resolveCurrentModulePathFromStack()}function resolveCurrentModulePathFromStack(){let e=Error.prepareStackTrace;try{Error.prepareStackTrace=(e,t)=>t;let e=Error().stack?.[0]?.getFileName();if(typeof e!=`string`||e.length===0)throw Error(`Failed to resolve the current module path from the stack trace.`);return e.startsWith(`file:`)?fileURLToPath(e):e}finally{Error.prepareStackTrace=e}}const require=createRequire(resolveCurrentModulePath());function isBuildOutputPackageRoot(e){return basename(e)===`dist`&&existsSync(join(dirname(e),`package.json`))}function resolvePackageBuildRoot(){let e=dirname(realpathSync(resolveCurrentModulePath()));for(;;){if(isBuildOutputPackageRoot(e))return e;let t=dirname(e);if(t===e)return null;e=t}}function findNearestPackageRoot(e){let n=e;for(;;){if(existsSync(join(n,`package.json`))&&!isBuildOutputPackageRoot(n))return n;let r=dirname(n);if(r===n)throw Error(`Failed to resolve package root from "${e}".`);n=r}}function resolvePackageRoot(){return findNearestPackageRoot(dirname(realpathSync(resolveCurrentModulePath())))}function tryResolvePackageRoot(){try{return resolvePackageRoot()}catch{return}}function rewriteSourceFilePathForBuild(e){return e.replace(/\.[cm]?tsx?$/,`.js`)}function resolvePackageSourceFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),e):join(t,rewriteSourceFilePathForBuild(e))}function resolvePackageSourceDirectoryPath(e){let t=resolvePackageBuildRoot();return join(t===null?resolvePackageRoot():t,e)}function resolvePackageDependencyPath(e){return require.resolve(e)}function resolvePackageCompiledFilePath(e){let t=resolvePackageBuildRoot();return t===null?join(resolvePackageRoot(),`.generated`,`compiled`,e.replace(/^src\/compiled\//,``)):join(t,e)}function normalizeInstalledPackageInfo(e){let t=e;if(!(typeof t.name!=`string`||typeof t.version!=`string`))return{name:t.name,version:t.version}}function tryReadInstalledPackageInfo(e,t){let r=normalizeInstalledPackageInfo(JSON.parse(readFileSync(e,`utf8`)));if(r?.name===t)return r}function resolveInstalledPackageInfo(){if(cachedPackageInfo)return cachedPackageInfo;let e=tryResolvePackageRoot(),t=e===void 0?void 0:tryReadInstalledPackageInfo(join(e,`package.json`),EVE_PACKAGE_NAME);if(t)return cachedPackageInfo=t,cachedPackageInfo;try{let e=tryReadInstalledPackageInfo(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),EVE_PACKAGE_NAME);if(e)return cachedPackageInfo=e,cachedPackageInfo}catch{}return cachedPackageInfo={...FALLBACK_PACKAGE_INFO},cachedPackageInfo}function readWorkflowVersionFromManifest(e){let t=e;for(let e of[t.devDependencies,t.dependencies,t.peerDependencies]){let t=e?.[`@workflow/core`];if(typeof t==`string`&&t.trim().length>0)return t}}function resolveExpectedWorkflowVersion(){let e=tryResolvePackageRoot();if(e!==void 0)try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(join(e,`package.json`),`utf8`)))}catch{}try{return readWorkflowVersionFromManifest(JSON.parse(readFileSync(require.resolve(`${EVE_PACKAGE_NAME}/package.json`),`utf8`)))}catch{return}}function resolveWorkflowModulePath(e){if(e===`workflow`)return resolvePackageSourceFilePath(`src/internal/workflow/index.ts`);if(e===`workflow/api`||e===`workflow/runtime`)return resolvePackageSourceFilePath(`src/internal/workflow/runtime.ts`);if(e===`workflow/internal/builtins`)return resolvePackageSourceFilePath(`src/internal/workflow/builtins.ts`);let t=WORKFLOW_MODULE_ALIASES[e];return t===void 0?require.resolve(e):resolvePackageCompiledFilePath(t)}export{resolveExpectedWorkflowVersion,resolveInstalledPackageInfo,resolvePackageDependencyPath,resolvePackageRoot,resolvePackageSourceDirectoryPath,resolvePackageSourceFilePath,resolveWorkflowModulePath};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectProviderOptions,expectString,getOptionalStringRecordProperty}from"#internal/authored-module.js";function normalizeAgentDefinition(e,r){let a=expectObjectRecord(e,r);if(expectOnlyKnownKeys(a,[`build`,`compaction`,`description`,`experimental`,`limits`,`model`,`modelContextWindowTokens`,`modelOptions`,`outputSchema`,`reasoning`],r),a.model===void 0)throw Error(`${r} The "model" field is required.`);let o={model:a.model};return a.description!==void 0&&(o.description=expectString(a.description,r)),a.compaction!==void 0&&(o.compaction=normalizeAgentCompactionDefinition(a.compaction,r)),a.build!==void 0&&(o.build=normalizeAgentBuildDefinition(a.build,r)),a.experimental!==void 0&&(o.experimental=normalizeAgentExperimentalDefinition(a.experimental,r)),a.modelOptions!==void 0&&(o.modelOptions=normalizeAgentModelOptions(a.modelOptions,r)),a.modelContextWindowTokens!==void 0&&(o.modelContextWindowTokens=expectPositiveInteger(a.modelContextWindowTokens,r)),a.outputSchema!==void 0&&(o.outputSchema=a.outputSchema),a.reasoning!==void 0&&(o.reasoning=normalizeAgentReasoningDefinition(a.reasoning,r)),a.limits!==void 0&&(o.limits=normalizeAgentLimitsDefinition(a.limits,r)),o}function normalizeAgentReasoningDefinition(e,t){let n=expectString(e,t);switch(n){case`provider-default`:case`none`:case`minimal`:case`low`:case`medium`:case`high`:case`xhigh`:return n;default:throw Error(t)}}function expectPositiveInteger(e,t){if(typeof e!=`number`||!Number.isInteger(e)||e<=0)throw Error(t);return e}function normalizeAgentLimitsDefinition(e,r){let i=expectObjectRecord(e,r);expectOnlyKnownKeys(i,[`maxInputTokensPerSession`,`maxOutputTokensPerSession`,`maxSubagentDepth`],r);let a={};return i.maxInputTokensPerSession!==void 0&&(a.maxInputTokensPerSession=
|
|
1
|
+
import{expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectProviderOptions,expectString,getOptionalStringRecordProperty}from"#internal/authored-module.js";function normalizeAgentDefinition(e,r){let a=expectObjectRecord(e,r);if(expectOnlyKnownKeys(a,[`build`,`compaction`,`description`,`experimental`,`limits`,`model`,`modelContextWindowTokens`,`modelOptions`,`outputSchema`,`reasoning`],r),a.model===void 0)throw Error(`${r} The "model" field is required.`);let o={model:a.model};return a.description!==void 0&&(o.description=expectString(a.description,r)),a.compaction!==void 0&&(o.compaction=normalizeAgentCompactionDefinition(a.compaction,r)),a.build!==void 0&&(o.build=normalizeAgentBuildDefinition(a.build,r)),a.experimental!==void 0&&(o.experimental=normalizeAgentExperimentalDefinition(a.experimental,r)),a.modelOptions!==void 0&&(o.modelOptions=normalizeAgentModelOptions(a.modelOptions,r)),a.modelContextWindowTokens!==void 0&&(o.modelContextWindowTokens=expectPositiveInteger(a.modelContextWindowTokens,r)),a.outputSchema!==void 0&&(o.outputSchema=a.outputSchema),a.reasoning!==void 0&&(o.reasoning=normalizeAgentReasoningDefinition(a.reasoning,r)),a.limits!==void 0&&(o.limits=normalizeAgentLimitsDefinition(a.limits,r)),o}function normalizeAgentReasoningDefinition(e,t){let n=expectString(e,t);switch(n){case`provider-default`:case`none`:case`minimal`:case`low`:case`medium`:case`high`:case`xhigh`:return n;default:throw Error(t)}}function expectPositiveInteger(e,t){if(typeof e!=`number`||!Number.isInteger(e)||e<=0)throw Error(t);return e}function expectPositiveIntegerOrFalse(e,t){return e===!1?!1:expectPositiveInteger(e,t)}function normalizeAgentLimitsDefinition(e,r){let i=expectObjectRecord(e,r);expectOnlyKnownKeys(i,[`maxInputTokensPerSession`,`maxOutputTokensPerSession`,`maxSubagentDepth`,`maxSubagents`],r);let a={};return i.maxInputTokensPerSession!==void 0&&(a.maxInputTokensPerSession=expectPositiveIntegerOrFalse(i.maxInputTokensPerSession,r)),i.maxOutputTokensPerSession!==void 0&&(a.maxOutputTokensPerSession=expectPositiveIntegerOrFalse(i.maxOutputTokensPerSession,r)),i.maxSubagentDepth!==void 0&&(a.maxSubagentDepth=expectPositiveInteger(i.maxSubagentDepth,r)),i.maxSubagents!==void 0&&(a.maxSubagents=expectPositiveInteger(i.maxSubagents,r)),a}function normalizeAgentBuildDefinition(e,r){let a=expectObjectRecord(e,r);expectOnlyKnownKeys(a,[`externalDependencies`],r);let o={};if(a.externalDependencies!==void 0){if(!Array.isArray(a.externalDependencies))throw Error(r);o.externalDependencies=Object.freeze(a.externalDependencies.map(e=>expectString(e,r)))}return o}function normalizeAgentWorkflowDefinition(e,r){let i=expectObjectRecord(e,r);expectOnlyKnownKeys(i,[`world`],r);let a={};return i.world!==void 0&&(a.world=normalizeAgentWorkflowWorldDefinition(i.world,r)),a}function normalizeAgentWorkflowWorldDefinition(e,t){let n=expectString(e,t);if(n.trim()===``)throw Error(`${t} "experimental.workflow.world" must be a non-empty package name.`);return n}function normalizeAgentExperimentalDefinition(e,r){let i=expectObjectRecord(e,r);expectOnlyKnownKeys(i,[`workflow`],r);let a={};return i.workflow!==void 0&&(a.workflow=normalizeAgentWorkflowDefinition(i.workflow,r)),a}function normalizeAgentModelOptions(e,i){let a=expectObjectRecord(e,i);expectOnlyKnownKeys(a,[`providerOptions`],i);let o=a.providerOptions;return o===void 0?{}:{providerOptions:expectProviderOptions(o,i)}}function normalizeAgentCompactionDefinition(e,r){let i=expectObjectRecord(e,r);expectOnlyKnownKeys(i,[`model`,`modelContextWindowTokens`,`thresholdPercent`],r);let a={};if(i.model!==void 0&&(a.model=i.model),i.modelContextWindowTokens!==void 0&&(a.modelContextWindowTokens=expectPositiveInteger(i.modelContextWindowTokens,r)),i.thresholdPercent!==void 0){let e=i.thresholdPercent;if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw Error(r);a.thresholdPercent=e}return a}function normalizeInstructionsDefinition(e,r){let a=expectObjectRecord(e,r);return expectOnlyKnownKeys(a,[`markdown`],r),{markdown:expectString(a.markdown,r)}}function normalizeSkillDefinition(e,r){let o=expectObjectRecord(e,r);expectOnlyKnownKeys(o,[`description`,`files`,`license`,`markdown`,`metadata`],r);let s={description:expectString(o.description,r),markdown:expectString(o.markdown,r)},c=o.license,l=getOptionalStringRecordProperty(o,`metadata`,r);return c!==void 0&&(s.license=expectString(c,r)),l!==void 0&&(s.metadata=l),o.files!==void 0&&(s.files=normalizeSkillFiles(o.files,r)),s}function normalizeSkillFiles(e,n){let r=expectObjectRecord(e,n),i={};for(let[e,t]of Object.entries(r)){if(typeof t==`string`||t instanceof Uint8Array){i[e]=t;continue}throw Error(`${n} Expected skill file "${e}" to be a string or Uint8Array.`)}return i}function normalizeScheduleDefinition(r,a){let o=expectObjectRecord(r,a);expectOnlyKnownKeys(o,[`cron`,`markdown`,`run`],a);let s=expectString(o.cron,a),c=o.markdown!==void 0,l=o.run!==void 0;if(c&&l)throw Error(`${a} Pass either "markdown" (fire-and-forget) or "run" (handler) — not both.`);if(!c&&!l)throw Error(`${a} Must provide either "markdown" (fire-and-forget) or "run" (handler).`);let u={cron:s};return c?u.markdown=expectString(o.markdown,a):u.run=expectFunction(o.run,a),u}export{normalizeAgentDefinition,normalizeInstructionsDefinition,normalizeScheduleDefinition,normalizeSkillDefinition};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectString}from"#internal/authored-module.js";import{isDynamicSentinel}from"#shared/dynamic-tool-definition.js";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";import{isDisabledToolSentinel}from"#public/definitions/tool.js";function
|
|
1
|
+
import{expectFunction,expectObjectRecord,expectOnlyKnownKeys,expectString}from"#internal/authored-module.js";import{isDynamicSentinel}from"#shared/dynamic-tool-definition.js";import{normalizeJsonSchemaDefinition}from"#internal/json-schema.js";import{isDisabledToolSentinel,isEnableWorkflowToolSentinel}from"#public/definitions/tool.js";function normalizeToolDefinition(e,t){if(isDynamicSentinel(e))return{kind:`dynamic-tool`,eventNames:Object.keys(e.events)};if(isDisabledToolSentinel(e))return{kind:`disabled`};if(isEnableWorkflowToolSentinel(e))return{kind:`enable-workflow`};let n=expectObjectRecord(e,t);expectOnlyKnownKeys(n,[`auth`,`description`,`execute`,`inputSchema`,`approval`,`outputSchema`,`toModelOutput`],t);let r=n.inputSchema===void 0?null:normalizeJsonSchemaDefinition(n.inputSchema),i=n.outputSchema===void 0?void 0:normalizeJsonSchemaDefinition(n.outputSchema,`output`),a={description:expectString(n.description,t),execute:expectFunction(n.execute,t),inputSchema:r};return i!==void 0&&(a.outputSchema=i),n.approval!==void 0&&expectFunction(n.approval,t),n.toModelOutput!==void 0&&expectFunction(n.toModelOutput,t),n.auth!==void 0&&expectFunction(expectObjectRecord(n.auth,t).getToken,t),{kind:`tool`,definition:a}}export{normalizeToolDefinition};
|