eve 0.79.1 → 0.80.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 +39 -0
- package/dist/src/channel/pending-authorization.d.ts +10 -0
- package/dist/src/channel/pending-authorization.js +1 -0
- package/dist/src/compiled/.vendor-stamp.json +7 -7
- package/dist/src/compiled/@chat-adapter/slack/api.d.ts +6 -0
- package/dist/src/compiled/@chat-adapter/slack/api.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/blocks.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/format.js +1 -1
- package/dist/src/compiled/@chat-adapter/slack/index.d.ts +14 -8
- package/dist/src/compiled/@chat-adapter/slack/index.js +33 -32
- package/dist/src/compiled/@chat-adapter/twilio/index.d.ts +37 -1
- package/dist/src/compiled/@chat-adapter/twilio/index.js +2 -2
- package/dist/src/compiled/@eve/tracing/index.js +1 -1
- package/dist/src/compiled/@eve/tracing/otel.js +1 -1
- package/dist/src/compiled/@linqapp/chat-sdk-adapter/index.js +1 -1
- package/dist/src/compiled/@photon-ai/chat-adapter-imessage/index.js +1 -1
- package/dist/src/compiled/@vercel/connect/index.js +5 -5
- package/dist/src/compiled/@vercel/connect/token.d.ts +11 -1
- package/dist/src/compiled/_chunks/node/chunk-NBSLXVG3-Bt7pDfyn.js +12 -0
- package/dist/src/compiled/_chunks/node/dist-BKsV21Vu.js +6 -0
- package/dist/src/compiled/_chunks/node/dist-CO_n_hUa.js +98 -0
- package/dist/src/compiled/_chunks/workflow/{mcp-C01bDEX-.js → mcp-Bwx_LQ4q.js} +4 -4
- package/dist/src/compiled/chat/index.js +1 -1
- package/dist/src/compiler/extension-compatibility.d.ts +18 -18
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/compiler/manifest.d.ts +8 -4
- package/dist/src/compiler/manifest.js +1 -1
- package/dist/src/compiler/normalize-connection.js +1 -1
- package/dist/src/compiler/normalize-manifest.js +1 -1
- package/dist/src/context/schedule-collection-tools.js +1 -1
- package/dist/src/execution/catalog/connection-auth.d.ts +4 -2
- package/dist/src/execution/catalog/connection-auth.js +1 -1
- package/dist/src/execution/catalog/connection-entry.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/proxied-deliver-step.js +1 -1
- package/dist/src/execution/publish-session-events.d.ts +13 -3
- package/dist/src/execution/publish-session-events.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/session/active-turn.d.ts +2 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn.d.ts +1 -0
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-event-stream.js +1 -1
- package/dist/src/execution/stable-workflow-names.d.ts +2 -0
- package/dist/src/execution/stable-workflow-names.js +1 -1
- package/dist/src/execution/tasks/task-id-input.js +1 -1
- package/dist/src/execution/tools/agent-router-workflow.js +1 -1
- package/dist/src/execution/tools/workflow/apply-run-messages-step.d.ts +6 -2
- package/dist/src/execution/tools/workflow/apply-run-messages-step.js +1 -1
- package/dist/src/execution/tools/workflow/body.d.ts +10 -1
- package/dist/src/execution/tools/workflow/body.js +1 -1
- package/dist/src/execution/tools/workflow/owner-inbox.js +1 -1
- package/dist/src/execution/tools/workflow/serve.js +1 -1
- package/dist/src/execution/web-fetch/execute.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +6 -0
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/extensions/git/extension/extension.d.ts +3 -1
- package/dist/src/extensions/git/extension/extension.js +1 -1
- package/dist/src/extensions/git/extension/lib/gh-tool.js +1 -1
- package/dist/src/extensions/git/extension/lib/github-shell.d.ts +14 -0
- package/dist/src/extensions/git/extension/lib/github-shell.js +1 -1
- package/dist/src/harness/action-result-helpers.js +1 -1
- package/dist/src/harness/attachment-staging.js +1 -1
- package/dist/src/harness/compaction/engine.js +3 -1
- package/dist/src/harness/compaction/prompt.d.ts +7 -0
- package/dist/src/harness/compaction/prompt.js +1 -1
- package/dist/src/harness/hitl/approvals.js +1 -1
- package/dist/src/harness/hitl/approved-calls.js +1 -1
- package/dist/src/harness/input-request-resolution.d.ts +2 -1
- package/dist/src/harness/input-request-resolution.js +1 -1
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/errors.d.ts +2 -2
- package/dist/src/harness/model-call/recovery.d.ts +2 -3
- package/dist/src/instrumentation/native-events.js +1 -1
- package/dist/src/instrumentation/session-init.d.ts +2 -1
- package/dist/src/instrumentation/session-init.js +1 -1
- package/dist/src/internal/application/optional-package-import.d.ts +5 -0
- package/dist/src/internal/application/optional-package-import.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/internal/authored-definition/connection.js +1 -1
- package/dist/src/internal/authored-definition/schedule-collection.js +1 -1
- package/dist/src/internal/nitro/host/application-route-registry.d.ts +7 -2
- package/dist/src/internal/nitro/host/application-route-registry.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +1 -1
- package/dist/src/internal/nitro/host/start-production-server.js +2 -2
- package/dist/src/internal/nitro/routes/channel-request-instrumentation.d.ts +3 -1
- package/dist/src/internal/nitro/routes/channel-request-instrumentation.js +1 -1
- package/dist/src/internal/nitro/routes/connection-events.d.ts +5 -0
- package/dist/src/internal/nitro/routes/connection-events.js +1 -0
- package/dist/src/internal/workflow-bundle/builder.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-ast-references.js +1 -1
- package/dist/src/protocol/message.d.ts +2 -0
- package/dist/src/protocol/message.js +1 -1
- package/dist/src/public/channels/slack/blocks.js +2 -2
- package/dist/src/public/channels/teams/authorization.d.ts +53 -0
- package/dist/src/public/channels/teams/authorization.js +1 -0
- package/dist/src/public/channels/teams/defaults.js +2 -2
- package/dist/src/public/channels/teams/hitl.d.ts +2 -1
- package/dist/src/public/channels/teams/teamsChannel.js +1 -1
- package/dist/src/public/channels/telegram/authorization-callback.js +1 -1
- package/dist/src/public/connections/index.d.ts +1 -0
- package/dist/src/public/definitions/connections/events.d.ts +43 -0
- package/dist/src/public/definitions/connections/events.js +1 -0
- package/dist/src/public/definitions/connections/mcp.d.ts +3 -0
- package/dist/src/public/next/index.js +1 -1
- package/dist/src/public/next/server.d.ts +11 -2
- package/dist/src/public/next/server.js +1 -1
- package/dist/src/public/schedules/subscription.d.ts +4 -3
- package/dist/src/runtime/connections/events/actions.d.ts +17 -0
- package/dist/src/runtime/connections/events/actions.js +1 -0
- package/dist/src/runtime/connections/events/delivery.d.ts +10 -0
- package/dist/src/runtime/connections/events/delivery.js +1 -0
- package/dist/src/runtime/connections/events/dispatch-step.d.ts +20 -0
- package/dist/src/runtime/connections/events/dispatch-step.js +1 -0
- package/dist/src/runtime/connections/events/lifecycle-step.d.ts +42 -0
- package/dist/src/runtime/connections/events/lifecycle-step.js +1 -0
- package/dist/src/runtime/connections/events/owner.d.ts +38 -0
- package/dist/src/runtime/connections/events/owner.js +1 -0
- package/dist/src/runtime/connections/events/path.d.ts +4 -0
- package/dist/src/runtime/connections/events/path.js +1 -0
- package/dist/src/runtime/connections/events/state.d.ts +37 -0
- package/dist/src/runtime/connections/events/state.js +1 -0
- package/dist/src/runtime/connections/events/workflow.d.ts +28 -0
- package/dist/src/runtime/connections/events/workflow.js +1 -0
- package/dist/src/runtime/connections/mcp-client.d.ts +4 -2
- package/dist/src/runtime/connections/mcp-client.js +1 -1
- package/dist/src/runtime/connections/openapi-client.js +1 -1
- package/dist/src/runtime/connections/scoped-authorization.js +1 -1
- package/dist/src/runtime/resolve-connection.js +1 -1
- package/dist/src/runtime/schedules/collection-client.d.ts +0 -2
- package/dist/src/runtime/schedules/collection-client.js +1 -1
- package/dist/src/runtime/types.d.ts +11 -0
- package/dist/src/setup/scaffold/create/add-to-project.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +2 -2
- package/dist/src/setup/scaffold/update/channels.js +1 -1
- package/dist/src/setup/scaffold/update/connections.js +2 -2
- package/dist/src/setup/scaffold/version-tokens.d.ts +1 -1
- package/dist/src/setup/scaffold/version-tokens.js +1 -1
- package/dist/src/shared/action-types.d.ts +1 -0
- package/dist/src/shared/action-types.js +1 -1
- package/dist/src/shared/agent-definition.d.ts +12 -4
- package/dist/src/shared/connection-events.d.ts +84 -0
- package/dist/src/shared/connection-events.js +1 -0
- package/dist/src/shared/connection-types.d.ts +10 -0
- package/dist/src/shared/validate-authorization.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/no-reply.d.ts +5 -0
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/dist/src/tools/signature.d.ts +4 -2
- package/dist/src/tools/signature.js +1 -1
- package/dist/src/tracing/eve/connection-events.d.ts +25 -0
- package/dist/src/tracing/eve/connection-events.js +1 -0
- package/dist/src/tracing/eve/install-instrumentation-runtime.js +1 -1
- package/dist/src/tracing/eve/mcp.d.ts +1 -0
- package/dist/src/tracing/eve/mcp.js +1 -1
- package/dist/src/tracing/eve/otel-declaration.d.ts +5 -0
- package/docs/agent-config.md +38 -13
- package/docs/channels/teams.mdx +6 -0
- package/docs/code-extension.mdx +28 -0
- package/docs/concepts/built-in-tools.md +3 -1
- package/docs/connections/mcp.mdx +105 -0
- package/docs/guides/hooks.md +4 -0
- package/docs/guides/instrumentation/instrumentation.mdx +2 -0
- package/docs/guides/instrumentation/otel.mdx +10 -0
- package/docs/sandbox/vercel.mdx +46 -0
- package/package.json +7 -7
- package/dist/src/compiled/_chunks/node/chunk-6QHBXN7B-gl4n6nmi.js +0 -12
- package/dist/src/compiled/_chunks/node/dist-DYDVZ-FS.js +0 -98
- package/dist/src/compiled/_chunks/node/dist-iEFkK9qw.js +0 -6
|
@@ -6,7 +6,7 @@ import { WorkflowToolRunAsks } from "#execution/tools/workflow/ask.js";
|
|
|
6
6
|
import type { WorkflowBodyCommand, WorkflowToolRunOutcome, WorkflowToolRunRef } from "#execution/tools/workflow/messages.js";
|
|
7
7
|
import type { WorkflowToolRunInbox } from "#execution/tools/workflow/owner.js";
|
|
8
8
|
import type { WorkflowToolRunEntry } from "#shared/action-types.js";
|
|
9
|
-
import type
|
|
9
|
+
import { type JsonObject, type JsonValue } from "#shared/json.js";
|
|
10
10
|
import type { ToolContext } from "#tools/definition.js";
|
|
11
11
|
export interface WorkflowBodyDefinition {
|
|
12
12
|
/** Everything the run needs to open `ctx.agent` sessions for its caller, and `ctx.agents`. */
|
|
@@ -52,6 +52,15 @@ export interface StartedWorkflowBody {
|
|
|
52
52
|
}
|
|
53
53
|
/** Starts the body of an `execute` or `task` call, which serves the call the run started with. */
|
|
54
54
|
export declare function startCallBody(input: WorkflowBodyInput): StartedWorkflowBody;
|
|
55
|
+
/**
|
|
56
|
+
* An authored result as the run's JSON outcome, parsed the way a local tool's
|
|
57
|
+
* result is: undefined properties are omitted, a missing result is `null`,
|
|
58
|
+
* and a value JSON can't carry throws, failing the run.
|
|
59
|
+
*/
|
|
60
|
+
export declare function toWorkflowOutput(call: {
|
|
61
|
+
readonly callId: string;
|
|
62
|
+
readonly toolName: string;
|
|
63
|
+
}, output: unknown): JsonValue;
|
|
55
64
|
/** A body's failure, or its cancellation when the run stopped. */
|
|
56
65
|
export declare function toFailedOutcome(error: unknown, runSignal: AbortSignal): WorkflowToolRunOutcome;
|
|
57
66
|
export declare function createWorkflowBodyRef(input: WorkflowBodyDefinition & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{callToolStubStep}from"#execution/tool-stubs/steps.js";import{getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createRunUsageTally}from"#execution/agent-sessions/usage.js";import{toolStubOutput}from"#tool-stubs/output.js";import{createAgentSessions}from"#execution/agent-sessions/session.js";import{WorkflowToolRunAsks,ask,attachWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{readRegisteredWorkflow}from"#execution/workflow-registry.js";const INTERRUPTED_OUTPUT={interrupted:!0};var WorkflowCallSignals=class{body=new AbortController;run=new AbortController;asks;constructor(e){this.asks=e}get abortSignal(){return this.body.signal}get runSignal(){return this.run.signal}get interrupted(){return this.body.signal.aborted&&!this.run.signal.aborted}get unwinding(){return this.run.signal.aborted}apply(e){switch(e.kind){case`cancel`:case`end`:this.asks.cancelAll(),this.run.abort(new WorkflowToolRunCancelledError(e.reason)),this.body.abort(this.run.signal.reason);return;case`interrupt`:this.body.abort(new WorkflowToolRunInterruptedError);return;case`call`:return}}};function startCallBody(e){let t=createWorkflowBodyRef(e),n=new WorkflowToolRunAsks(t.runId),r=new WorkflowCallSignals(n),i={agentContext:e.agentContext,asks:n,auth:e.session.auth,control:e.hookToken,from:t,owner:e.owner},a=createRunUsageTally(),o=createAgentSessions(i,a),s=createCallContext(e,r,o.open);return attachWorkflowToolRunContext(s,i),{asks:n,close:o.close,control:r,outcome:executeCallBody(e,s,r,t),usage:a}}async function executeCallBody(e,t,n,r){try{let n=findStubTarget(e.agentContext.toolStubs,e.toolName);if(n!==void 0){let t=await callToolStubStep(n.scope,{callId:stubCallId(e.session.id,e.session.turn.id,e.callId),tool:n.tool,input:e.input});if(t.kind===`error`)throw Error(t.error);if(t.kind===`stub`)return{output:toolStubOutput(t.outcome),status:`completed`}}let i=resolveWorkflowEntryPoint(e)(e.executeInput??e.input,t),a;if(!isAsyncIterable(i))a=await i;else{let t=i[Symbol.asyncIterator](),n,o=await t.next();for(;o.done!==!0;)n=o.value,await e.owner.send({from:r,kind:`report`,update:o.value}),o=await t.next();a=o.value??n
|
|
1
|
+
import{parseJsonValue}from"#shared/json.js";import{callToolStubStep}from"#execution/tool-stubs/steps.js";import{getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{normalizeSerializableError}from"#execution/workflow-errors.js";import{createRunUsageTally}from"#execution/agent-sessions/usage.js";import{toolStubOutput}from"#tool-stubs/output.js";import{createAgentSessions}from"#execution/agent-sessions/session.js";import{WorkflowToolRunAsks,ask,attachWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{readRegisteredWorkflow}from"#execution/workflow-registry.js";import{withToolOutputSerializationError}from"#harness/tool-output-serialization.js";const INTERRUPTED_OUTPUT={interrupted:!0};var WorkflowCallSignals=class{body=new AbortController;run=new AbortController;asks;constructor(e){this.asks=e}get abortSignal(){return this.body.signal}get runSignal(){return this.run.signal}get interrupted(){return this.body.signal.aborted&&!this.run.signal.aborted}get unwinding(){return this.run.signal.aborted}apply(e){switch(e.kind){case`cancel`:case`end`:this.asks.cancelAll(),this.run.abort(new WorkflowToolRunCancelledError(e.reason)),this.body.abort(this.run.signal.reason);return;case`interrupt`:this.body.abort(new WorkflowToolRunInterruptedError);return;case`call`:return}}};function startCallBody(e){let t=createWorkflowBodyRef(e),n=new WorkflowToolRunAsks(t.runId),r=new WorkflowCallSignals(n),i={agentContext:e.agentContext,asks:n,auth:e.session.auth,control:e.hookToken,from:t,owner:e.owner},a=createRunUsageTally(),o=createAgentSessions(i,a),s=createCallContext(e,r,o.open);return attachWorkflowToolRunContext(s,i),{asks:n,close:o.close,control:r,outcome:executeCallBody(e,s,r,t),usage:a}}async function executeCallBody(e,t,n,r){try{let n=findStubTarget(e.agentContext.toolStubs,e.toolName);if(n!==void 0){let t=await callToolStubStep(n.scope,{callId:stubCallId(e.session.id,e.session.turn.id,e.callId),tool:n.tool,input:e.input});if(t.kind===`error`)throw Error(t.error);if(t.kind===`stub`)return{output:toolStubOutput(t.outcome),status:`completed`}}let i=resolveWorkflowEntryPoint(e)(e.executeInput??e.input,t),a;if(!isAsyncIterable(i))a=await i;else{let t=i[Symbol.asyncIterator](),n,o=await t.next();for(;o.done!==!0;)n=o.value,await e.owner.send({from:r,kind:`report`,update:o.value}),o=await t.next();a=o.value??n}return{output:toWorkflowOutput(e,a),status:`completed`}}catch(e){return n.interrupted?{output:INTERRUPTED_OUTPUT,status:`completed`}:toFailedOutcome(e,n.runSignal)}}function toWorkflowOutput(e,t){return withToolOutputSerializationError({boundary:`execute`,toolCallId:e.callId,toolName:e.toolName},()=>parseJsonValue(t??null))}function toFailedOutcome(e,t){if(t.aborted){let{reason:e}=t;return{reason:e instanceof Error?e.message:String(e??``),status:`cancelled`}}return{error:normalizeSerializableError(e),status:`failed`}}function createWorkflowBodyRef(e){let t={callId:e.callId,input:e.input,runId:e.runId??getWorkflowMetadata().workflowRunId,sequence:e.session.turn.sequence,stepIndex:e.stepIndex,toolName:e.toolName,turnId:e.session.turn.id};return e.entry.entryPoint===`execute`?t:{...t,taskId:e.entry.taskId}}function resolveWorkflowEntryPoint(e){let t=readRegisteredWorkflow(e.workflowId);if(typeof t!=`function`)throw Error(`Tool "${e.toolName}" is not registered as a workflow in this deployment (${e.workflowId}). The tool was renamed or removed after this run started.`);return t}function createSharedContext(e,t,n){let unavailable=(t,n)=>{throw Error(`ctx.${t} is not available inside a workflow tool; ${n}. Tool "${e.toolName}" runs as a durable workflow body, which only replays deterministic code.`)};return{agent:t,ask:n,getSandbox:()=>unavailable(`getSandbox()`,`the session sandbox belongs to the turn`),getToken:()=>unavailable(`getToken()`,`pass ctx directly to a "use step" helper to resolve credentials`),requireAuth:()=>unavailable(`requireAuth()`,`pass ctx directly to a "use step" helper to request authorization`),toolName:e.toolName}}function createAgentsView(e){return Object.freeze(Object.fromEntries(Object.entries(e.agents).map(([e,t])=>[e,Object.freeze({...t})])))}function createCallContext(e,t,n){let r={...createSharedContext(e,n,(e,t)=>ask(r,e,t)),abortSignal:t.abortSignal,agents:createAgentsView(e.agentContext),callId:e.callId,session:e.session};return r}function isAsyncIterable(e){return typeof e==`object`&&!!e&&typeof e[Symbol.asyncIterator]==`function`}var WorkflowToolRunCancelledError=class extends Error{constructor(e){super(e),this.name=`WorkflowToolRunCancelledError`}},WorkflowToolRunInterruptedError=class extends Error{constructor(){super(`A new message arrived while the turn waited on this call.`),this.name=`WorkflowToolRunInterruptedError`}};export{WorkflowToolRunCancelledError,WorkflowToolRunInterruptedError,createAgentsView,createSharedContext,createWorkflowBodyRef,resolveWorkflowEntryPoint,startCallBody,toFailedOutcome,toWorkflowOutput};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseJsonValue}from"#shared/json.js";function workflowToolRunOutcomeToToolResult(e){let{from:t,result:n}=e;return n.status===`completed`?{callId:t.callId,kind:`tool-result`,output:n.output,toolName:t.toolName}:{callId:t.callId,isError:!0,kind:`tool-result`,output:
|
|
1
|
+
import{parseJsonValue}from"#shared/json.js";import{rebuildSerializableError}from"#execution/workflow-errors.js";function workflowToolRunOutcomeToToolResult(e){let{from:t,result:n}=e;return n.status===`completed`?{callId:t.callId,kind:`tool-result`,output:n.output,toolName:t.toolName}:n.status===`failed`?{callId:t.callId,errorName:rebuildSerializableError(n.error).name,isError:!0,kind:`tool-result`,output:workflowToolRunFailureOutput(e),toolName:t.toolName}:{callId:t.callId,isError:!0,kind:`tool-result`,output:n.reason??`The workflow tool run was cancelled.`,toolName:t.toolName}}function workflowToolRunFailureOutput(e){if(e.result.status!==`failed`)throw TypeError(`Expected a failed workflow outcome.`);let t=parseJsonValueOrUndefined(e.result.error);return t!==void 0&&typeof t==`object`&&t&&!Array.isArray(t)&&typeof Reflect.get(t,`code`)==`string`?t:errorMessage(e.result.error)}function errorMessage(e){if(typeof e==`object`&&e&&`message`in e){let t=e.message;if(typeof t==`string`)return t}return String(e)}function parseJsonValueOrUndefined(e){try{return parseJsonValue(e)}catch{return}}function workflowToolRunRequestToInputRequestPayload(e){let{from:t,replyTo:n,requestCoordinates:r}=e;return{callId:t.callId,childContinuationToken:n,childSessionId:t.runId,childSessionInbox:e.childSessionInbox,remote:e.remote,inputSource:e.inputSource,event:{requests:workflowToolRunInputRequests(e),sequence:r?.sequence??t.sequence,stepIndex:r?.stepIndex??t.stepIndex,taskId:t.taskId,turnId:r?.turnId??t.turnId},kind:`subagent-input-request`,subagentName:t.toolName}}function workflowToolRunInputRequests(e){return e.request.kind===`input-batch`?e.request.requests:[normalizeInputRequest(e.request,e.from,e.replyTo)]}function normalizeInputRequest(e,t,n){switch(e.kind){case`authorization-request`:throw TypeError(`A workflow authorization event cannot be normalized as human input.`);case`ask`:return normalizeAskRequest(e.request,t,n);default:return e}}function normalizeAskRequest(e,t,n){if(typeof e.prompt!=`string`||e.prompt.length===0)throw TypeError("A workflow tool run request needs a non-empty `prompt`.");let r={action:{callId:t.callId,input:t.input,kind:`tool-call`,toolName:t.toolName},kind:`question`,prompt:e.prompt,requestId:n};return e.allowFreeform!==void 0&&(r.allowFreeform=e.allowFreeform),e.display!==void 0&&(r.display=e.display),e.options!==void 0&&(r.options=[...e.options]),r}export{workflowToolRunFailureOutput,workflowToolRunInputRequests,workflowToolRunOutcomeToToolResult,workflowToolRunRequestToInputRequestPayload};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{callToolStubStep}from"#execution/tool-stubs/steps.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{createRunUsageTally}from"#execution/agent-sessions/usage.js";import{toolStubOutput}from"#tool-stubs/output.js";import{createAgentSessions}from"#execution/agent-sessions/session.js";import{WorkflowToolRunAsks,ask,attachWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{WorkflowToolRunCancelledError,createAgentsView,createSharedContext,createWorkflowBodyRef,resolveWorkflowEntryPoint,toFailedOutcome}from"#execution/tools/workflow/body.js";var WorkflowServeCalls=class{asks;run=new AbortController;first;runRef;runSession;owner;usage=createRunUsageTally(()=>this.sendUncarriedUsage());carriedUsage;toolName;seenCallIds;firstReceived=!1;arrived=[];waiting;latest;pendingReceive;stretch;unwindingCancel=!1;endedBy;replies=Promise.resolve();constructor(e){this.runRef=createWorkflowBodyRef(e),this.asks=new WorkflowToolRunAsks(this.runRef.runId),this.runSession=e.session,this.owner=e.owner,this.toolName=e.toolName,this.seenCallIds=new Set([e.callId]),this.first=this.serve({agentContext:e.agentContext,auth:e.session.auth,callId:this.runRef.callId,executeInput:e.executeInput,input:this.runRef.input,sequence:this.runRef.sequence,stepIndex:this.runRef.stepIndex,turnId:this.runRef.turnId}),this.waiting=[this.first],this.latest=this.first}get runSignal(){return this.run.signal}get unwinding(){return this.run.signal.aborted||this.unwindingCancel}get currentSignal(){return this.stretch?.signal??this.run.signal}get current(){return this.latest}apply(e){switch(e.kind){case`call`:this.accept(e.call);return;case`cancel`:this.cancel(new WorkflowToolRunCancelledError(e.reason));return;case`end`:this.end(new WorkflowToolRunCancelledError(e.reason));return;case`interrupt`:return}}receive(){if(!this.firstReceived)return this.firstReceived=!0,Promise.resolve(this.first.call);if(this.unwindingCancel=!1,this.pendingReceive!==void 0)return this.pendingReceive.promise;if(this.endedBy!==void 0)return Promise.reject(this.endedBy);let e=this.arrived.shift();return e===void 0?(this.pendingReceive=createPendingReceive(),this.pendingReceive.promise):(this.take(e),Promise.resolve(e.call))}reply(e){let t=this.waiting;if(t.length===0)return;this.waiting=[],this.arrived.length===0&&(this.stretch=void 0),this.asks.withdrawAll();let n=this.replies;this.replies=n.then(()=>this.deliverReply(t,e))}assertWaiting(){if(!(this.waiting.length>0))throw Error(`ctx.ask() needs a call waiting for a result, but tool "${this.toolName}" already replied to every call it received.`)}async flush(){await this.asks.flush(),await this.replies}sendUncarriedUsage(){if(this.waiting.length>0||this.endedBy!==void 0)return;let{from:e}=this.latest;this.replies=this.replies.then(async()=>{let t=this.usage.total();t===void 0||isSameUsage(t,this.carriedUsage)||(this.carriedUsage=t,await this.owner.send({from:e,kind:`usage`,usage:t}))})}accept(e){if(this.endedBy!==void 0||this.seenCallIds.has(e.callId))return;this.seenCallIds.add(e.callId);let t=this.serve(e),n=this.pendingReceive;if(n===void 0){this.arrived.push(t);return}this.pendingReceive=void 0,this.take(t),n.resolve(t.call)}take(e){this.waiting.push(e),this.latest=e}cancel(e){this.pendingReceive===void 0&&(this.unwindingCancel=!0),this.stretch?.abort(e),this.stretch=void 0,this.waiting=[],this.arrived=[]}end(e){this.asks.cancelAll(),this.endedBy=e,this.run.abort(e),this.stretch?.abort(e);let t=this.pendingReceive;this.pendingReceive=void 0,t?.reject(e)}serve(e){return this.stretch??=new AbortController,{agentContext:e.agentContext,agents:createAgentsView(e.agentContext),call:{abortSignal:this.stretch.signal,callId:e.callId,input:e.executeInput??e.input},from:{...this.runRef,callId:e.callId,input:e.input,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},session:{...this.runSession,auth:e.auth,turn:{id:e.turnId,sequence:e.sequence}}}}async deliverReply(e,t){let n=e.at(-1);if(n===void 0)return;let r=e.map(e=>e.from.callId),i=this.usage.total();this.carriedUsage=i,await this.owner.send({callIds:r,from:n.from,kind:`reply`,output:t,...i!==void 0&&{usage:i}})}};function isSameUsage(e,t){return t!==void 0&&e.inputTokens===t.inputTokens&&e.outputTokens===t.outputTokens&&e.cacheReadTokens===t.cacheReadTokens&&e.cacheWriteTokens===t.cacheWriteTokens&&e.costUsd===t.costUsd}function startServeBody(e){let t=new WorkflowServeCalls(e),n={get agentContext(){return t.current.agentContext},asks:t.asks,get auth(){return t.current.session.auth},control:e.hookToken,get from(){return t.current.from},owner:e.owner},r=createAgentSessions(n,t.usage),i=createServeContext(e,t,r.open);return attachWorkflowToolRunContext(i,n),{asks:t.asks,close:r.close,control:t,outcome:executeServeBody(e,t,i),usage:t.usage}}async function executeServeBody(e,t,n){let r;try{let i=findStubTarget(e.agentContext.toolStubs,e.toolName),receive=()=>t.receive()
|
|
1
|
+
import{callToolStubStep}from"#execution/tool-stubs/steps.js";import{findStubTarget,stubCallId}from"#tool-stubs/target.js";import{createRunUsageTally}from"#execution/agent-sessions/usage.js";import{toolStubOutput}from"#tool-stubs/output.js";import{createAgentSessions}from"#execution/agent-sessions/session.js";import{WorkflowToolRunAsks,ask,attachWorkflowToolRunContext}from"#execution/tools/workflow/ask.js";import{WorkflowToolRunCancelledError,createAgentsView,createSharedContext,createWorkflowBodyRef,resolveWorkflowEntryPoint,toFailedOutcome,toWorkflowOutput}from"#execution/tools/workflow/body.js";var WorkflowServeCalls=class{asks;run=new AbortController;first;runRef;runSession;owner;usage=createRunUsageTally(()=>this.sendUncarriedUsage());carriedUsage;toolName;seenCallIds;firstReceived=!1;arrived=[];waiting;latest;pendingReceive;stretch;unwindingCancel=!1;endedBy;replies=Promise.resolve();constructor(e){this.runRef=createWorkflowBodyRef(e),this.asks=new WorkflowToolRunAsks(this.runRef.runId),this.runSession=e.session,this.owner=e.owner,this.toolName=e.toolName,this.seenCallIds=new Set([e.callId]),this.first=this.serve({agentContext:e.agentContext,auth:e.session.auth,callId:this.runRef.callId,executeInput:e.executeInput,input:this.runRef.input,sequence:this.runRef.sequence,stepIndex:this.runRef.stepIndex,turnId:this.runRef.turnId}),this.waiting=[this.first],this.latest=this.first}get runSignal(){return this.run.signal}get unwinding(){return this.run.signal.aborted||this.unwindingCancel}get currentSignal(){return this.stretch?.signal??this.run.signal}get current(){return this.latest}apply(e){switch(e.kind){case`call`:this.accept(e.call);return;case`cancel`:this.cancel(new WorkflowToolRunCancelledError(e.reason));return;case`end`:this.end(new WorkflowToolRunCancelledError(e.reason));return;case`interrupt`:return}}receive(){if(!this.firstReceived)return this.firstReceived=!0,Promise.resolve(this.first.call);if(this.unwindingCancel=!1,this.pendingReceive!==void 0)return this.pendingReceive.promise;if(this.endedBy!==void 0)return Promise.reject(this.endedBy);let e=this.arrived.shift();return e===void 0?(this.pendingReceive=createPendingReceive(),this.pendingReceive.promise):(this.take(e),Promise.resolve(e.call))}reply(e){let t=this.waiting;if(t.length===0)return;this.waiting=[],this.arrived.length===0&&(this.stretch=void 0),this.asks.withdrawAll();let n=this.replies;this.replies=n.then(()=>this.deliverReply(t,e))}assertWaiting(){if(!(this.waiting.length>0))throw Error(`ctx.ask() needs a call waiting for a result, but tool "${this.toolName}" already replied to every call it received.`)}async flush(){await this.asks.flush(),await this.replies}sendUncarriedUsage(){if(this.waiting.length>0||this.endedBy!==void 0)return;let{from:e}=this.latest;this.replies=this.replies.then(async()=>{let t=this.usage.total();t===void 0||isSameUsage(t,this.carriedUsage)||(this.carriedUsage=t,await this.owner.send({from:e,kind:`usage`,usage:t}))})}accept(e){if(this.endedBy!==void 0||this.seenCallIds.has(e.callId))return;this.seenCallIds.add(e.callId);let t=this.serve(e),n=this.pendingReceive;if(n===void 0){this.arrived.push(t);return}this.pendingReceive=void 0,this.take(t),n.resolve(t.call)}take(e){this.waiting.push(e),this.latest=e}cancel(e){this.pendingReceive===void 0&&(this.unwindingCancel=!0),this.stretch?.abort(e),this.stretch=void 0,this.waiting=[],this.arrived=[]}end(e){this.asks.cancelAll(),this.endedBy=e,this.run.abort(e),this.stretch?.abort(e);let t=this.pendingReceive;this.pendingReceive=void 0,t?.reject(e)}serve(e){return this.stretch??=new AbortController,{agentContext:e.agentContext,agents:createAgentsView(e.agentContext),call:{abortSignal:this.stretch.signal,callId:e.callId,input:e.executeInput??e.input},from:{...this.runRef,callId:e.callId,input:e.input,sequence:e.sequence,stepIndex:e.stepIndex,turnId:e.turnId},session:{...this.runSession,auth:e.auth,turn:{id:e.turnId,sequence:e.sequence}}}}async deliverReply(e,t){let n=e.at(-1);if(n===void 0)return;let r=e.map(e=>e.from.callId),i=this.usage.total();this.carriedUsage=i,await this.owner.send({callIds:r,from:n.from,kind:`reply`,output:t,...i!==void 0&&{usage:i}})}};function isSameUsage(e,t){return t!==void 0&&e.inputTokens===t.inputTokens&&e.outputTokens===t.outputTokens&&e.cacheReadTokens===t.cacheReadTokens&&e.cacheWriteTokens===t.cacheWriteTokens&&e.costUsd===t.costUsd}function startServeBody(e){let t=new WorkflowServeCalls(e),n={get agentContext(){return t.current.agentContext},asks:t.asks,get auth(){return t.current.session.auth},control:e.hookToken,get from(){return t.current.from},owner:e.owner},r=createAgentSessions(n,t.usage),i=createServeContext(e,t,r.open);return attachWorkflowToolRunContext(i,n),{asks:t.asks,close:r.close,control:t,outcome:executeServeBody(e,t,i),usage:t.usage}}async function executeServeBody(e,t,n){let r;try{let i=findStubTarget(e.agentContext.toolStubs,e.toolName),receive=()=>t.receive(),a=i===void 0?await resolveWorkflowEntryPoint(e)(receive,n):await serveStub(i.scope,i.tool,receive,n);r={output:toWorkflowOutput(e,a),status:`completed`}}catch(e){r=toFailedOutcome(e,t.runSignal)}return await t.flush(),r}function createServeContext(e,t,n){let r={...createSharedContext(e,n,(e,n)=>(t.assertWaiting(),ask(r,e,n))),get abortSignal(){return t.currentSignal},get agents(){return t.current.agents},get callId(){return t.current.from.callId},get session(){return t.current.session},reply:n=>t.reply(toWorkflowOutput({callId:r.callId,toolName:e.toolName},n))};return r}function createPendingReceive(){let e,t;return{promise:new Promise((n,r)=>{e=n,t=r}),reject:t,resolve:e}}async function serveStub(e,t,n,r){for(;;){let i=await n();if(i.abortSignal.aborted)continue;let a=await callToolStubStep(e,{callId:stubCallId(r.session.id,r.session.turn.id,i.callId),input:i.input,tool:t,persistent:!0});if(a.kind!==`stub`)throw Error(a.kind===`error`?a.error:`Persistent stub configuration changed.`);r.reply(toolStubOutput(a.outcome))}}export{startServeBody};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{truncateHead}from"#execution/sandbox/truncate-output.js";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{convertHtmlToMarkdown,extractTextFromHtml}from"#execution/web-fetch/html.js";import{requestPublicUrl}from"#execution/web-fetch/request.js";const MAX_RESPONSE_SIZE=5242880;async function executeWebFetchTool(e,t){let{url:n,format:r=`markdown`,timeout:i}=e,a=Math.min(i===void 0?3e4:i*1e3,12e4),o=AbortSignal.timeout(a),s=t?.abortSignal===void 0?o:AbortSignal.any([t.abortSignal,o]),c=buildHeaders(r),l=await requestPublicUrl(n,{headers:c,maxResponseSize:MAX_RESPONSE_SIZE,signal:s}),u=l.status===403&&l.headers.get(`cf-mitigated`)===`challenge`?await requestPublicUrl(n,{headers:{...c,"User-Agent":EVE_PACKAGE_NAME},maxResponseSize:MAX_RESPONSE_SIZE,signal:s}):l,d=await u.arrayBuffer(),f=u.headers.get(`content-type`)??``,p=f.includes(`text/html`)
|
|
1
|
+
import{truncateHead}from"#execution/sandbox/truncate-output.js";import{EVE_PACKAGE_NAME}from"#internal/package-name.js";import{convertHtmlToMarkdown,extractTextFromHtml}from"#execution/web-fetch/html.js";import{requestPublicUrl}from"#execution/web-fetch/request.js";const MAX_RESPONSE_SIZE=5242880;async function executeWebFetchTool(e,t){let{url:n,format:r=`markdown`,timeout:i}=e,a=Math.min(i===void 0?3e4:i*1e3,12e4),o=AbortSignal.timeout(a),s=t?.abortSignal===void 0?o:AbortSignal.any([t.abortSignal,o]),c=buildHeaders(r),l=await requestPublicUrl(n,{headers:c,maxResponseSize:MAX_RESPONSE_SIZE,signal:s}),u=l.status===403&&l.headers.get(`cf-mitigated`)===`challenge`?await requestPublicUrl(n,{headers:{...c,"User-Agent":EVE_PACKAGE_NAME},maxResponseSize:MAX_RESPONSE_SIZE,signal:s}):l,d=await u.arrayBuffer(),f=u.headers.get(`content-type`)??``,p=new TextDecoder().decode(d),m=f.includes(`text/html`)||f.trim()===``&&/^\s*<(?:!doctype\s+html|html)[\s>]/i.test(p),h;if(h=r===`markdown`&&m?convertHtmlToMarkdown(p):r===`text`&&m?extractTextFromHtml(p):p,!u.ok){let e=`Request failed with status code: ${u.status}`;h=h.length===0?e:`${e}\n\n${h}`}let{output:g,truncated:_}=truncateHead(h);return{content:g,contentType:f,truncated:_,url:n}}function buildHeaders(e){let t;return t=e===`markdown`?`text/markdown;q=1.0, text/x-markdown;q=0.9, text/plain;q=0.8, text/html;q=0.7, */*;q=0.1`:e===`text`?`text/plain;q=1.0, text/markdown;q=0.9, text/html;q=0.8, */*;q=0.1`:`text/html;q=1.0, application/xhtml+xml;q=0.9, text/plain;q=0.8, text/markdown;q=0.7, */*;q=0.1`,{Accept:t,"Accept-Language":`en-US,en;q=0.9`,"User-Agent":`Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36`}}export{executeWebFetchTool};
|
|
@@ -24,6 +24,12 @@ export declare const sessionTimeoutWorkflowReference: {
|
|
|
24
24
|
export declare const workflowToolRunWorkflowReference: {
|
|
25
25
|
workflowId: string;
|
|
26
26
|
};
|
|
27
|
+
export declare const connectionEventWorkflowReference: {
|
|
28
|
+
workflowId: string;
|
|
29
|
+
};
|
|
30
|
+
export declare const connectionEventDeliveryWorkflowReference: {
|
|
31
|
+
workflowId: string;
|
|
32
|
+
};
|
|
27
33
|
/**
|
|
28
34
|
* Creates a workflow-backed runtime whose current owner executes turns and
|
|
29
35
|
* whose original run retains the public event stream across owner handoffs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{SessionPredecessorKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{validateToolStubTargets}from"#tool-stubs/validate-targets.js";import{getHookByToken,getRun,getWorld,start}from"#internal/workflow/runtime.js";import{SessionStrandedError,describeStrandedSession}from"#channel/session-stranded-error.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{serializeContext}from"#context/serialize.js";import{AcceptedSessionIdentityError,SessionHandoffPendingError,logicalSessionToken,resolveSessionInbox,resumeSessionInbox}from"#execution/session-inbox/resume.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{StrandedSessionOwnerError,assertRunnableSessionInbox,findSessionHookHolder}from"#execution/session-inbox/owner.js";import{initializeSessionInstrumentation}from"#instrumentation/runtime.js";import{EVE_VERSION_ATTRIBUTE,buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{endStrandedSession}from"#execution/session-inbox/end-stranded-session.js";import{SESSION_HOOK_HANDOVER_TIMEOUT_MS,waitForSessionHooksRelease}from"#execution/session-inbox/hook-release.js";import{SESSION_TIMEOUT_WORKFLOW_NAME,WORKFLOW_ENTRY_NAME,WORKFLOW_TOOL_RUN_WORKFLOW_NAME}from"#execution/stable-workflow-names.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{readSessionEventHistory,readSessionEventStream,readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{SESSION_HANDOFF_VERSION}from"#execution/session/entry-input.js";import{buildInvocationAttributes}from"#internal/invocation/metadata.js";import{isAgentTraceContext}from"#tracing/eve/agent-trace-context.js";const EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},sessionTimeoutWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${SESSION_TIMEOUT_WORKFLOW_NAME}`},workflowToolRunWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_TOOL_RUN_WORKFLOW_NAME}`};function createWorkflowRuntime(e){let startSession=async(t,n)=>{let r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId});t.toolStubs!==void 0&&t.toolStubs.rootSessionId===void 0&&validateToolStubTargets(t.toolStubs.rules,r.graph);let i=buildRunContext({bundle:r,dynamicSubagentAgentConfig:e.dynamicSubagentAgentConfig,run:t});n!==void 0&&i.set(SessionPredecessorKey,n);let a=resolveEffectiveAgentRuntime(r,i);initializeSessionInstrumentation({agentName:a.turnAgent.id,ctx:i});let o=a.limits?.sessionTimeoutMs,s=r.resolvedAgent.config?.experimental?.workflow?.retention,c=serializeContext(i),l=readParentLineage(c),u={kind:`initial`,input:t.input,ownerDeploymentId:await resolveCurrentWorkflowDeploymentId(),serializedContext:c};t.limits!==void 0&&(u.limits=t.limits),t.continuationConflictCommand!==void 0&&(u.continuationConflictCommand=t.continuationConflictCommand),o!==void 0&&(u.sessionTimeoutMs=o),s!==void 0&&(u.retention=s);let d={...l.sessionId===void 0?buildSessionAttributes({serializedContext:c}):buildSubagentRootAttributes({identity:{nodeId:r.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:l.callId,parentSessionId:l.sessionId,parentTurnId:l.turnId,rootSessionId:l.rootSessionId??l.sessionId,serializedContext:c}),...t.externalInvocation===void 0?{}:buildInvocationAttributes(t.externalInvocation)},f;try{let e={allowReservedAttributes:!0,attributes:normalizeEveAttributes(d)};s!==void 0&&(e.experimental_retention=s),f=await startWorkflowOnDeployment(workflowEntryReference,[u],u.ownerDeploymentId,e)}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:t.continuationToken}),e}let p,getEvents=()=>(p??=readSessionEventStream(f.runId),p);return{get events(){return getEvents()},sessionId:f.runId}};return{async createSession(e){return await startSession(e)},async dispatchContinuation(e){let{command:t,continuationToken:n,successor:r}=e;try{return await dispatchWorkflowCommand(n,t)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;if(t.kind!==`send`||r===void 0)return await settleStrandedCommand(n,t,e);if((t.payload.inputResponses?.length??0)>0)throw sessionStrandedError(e,`Its pending requests can no longer be answered; send a new message to start a fresh session.`);let i=await endStrandedSession(e,n,`message`);return{sessionId:(await startSession(r,{sessionId:i})).sessionId,status:`accepted`}}},async dispatchSession(e){return await dispatchWorkflowSessionCommand(e)},async getEventStream(e,t){if(t?.follow===!1)return readSessionEventHistory(e,t.startIndex);try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(e)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return readSessionEventStream(e,t?.startIndex)},async getStreamTailIndex(e){return await readSessionStreamTailIndex(e)},resolveContinuation}}async function startSessionOwnerStep(e){"use step";let{activationToken:t,anchorRunId:n,checkpoint:r,targetDeploymentId:i,...a}=e,o={...a,activationToken:t,checkpoint:r,handoffVersion:SESSION_HANDOFF_VERSION,kind:`handoff`,ownerDeploymentId:i,sessionWritable:getRun(n).getWritable(),sessionId:n};await startWorkflowOnDeployment(workflowEntryReference,[o],i,r.retention===void 0?void 0:{experimental_retention:r.retention})}async function dispatchWorkflowCommand(e,t){let n;try{let r=await resumeSessionInbox(e,t);n={runId:r.ownerRunId,sessionId:await r.sessionId}}catch(n){if(n instanceof StrandedSessionOwnerError)throw n;let r=t.kind===`send`&&typeof e!=`string`,i={status:`session_not_active`,retryable:!0};if(n instanceof SessionHandoffPendingError){if(r)return i;throw n}if(isInactiveCommandTarget(n))return r&&await isRunActive(e.sessionId)?i:inactiveCommandResult(t);throw logError(log,`failed to dispatch session command`,n,{command:t.kind,token:e}),n}return t.kind===`reset`&&await waitForSessionHooksRelease([sessionCommandHookToken(n.sessionId),logicalSessionToken(e)],n.runId),activeCommandResult(t,n.sessionId)}async function settleStrandedCommand(e,t,n){switch(t.kind){case`reset`:return{previousSessionId:await endStrandedSession(n,e,`reset`),status:`reset`};case`send`:case`clear`:throw sessionStrandedError(n);default:return inactiveCommandResult(t)}}function sessionStrandedError(e,t){let n=e.eveVersion===void 0?{}:{eveVersion:e.eveVersion};return new SessionStrandedError(n,describeStrandedSession(n,t))}function activeCommandResult(e,t){return e.kind===`reset`?{previousSessionId:t,status:`reset`}:e.kind===`send`&&e.delivery!==void 0?{sessionId:t,status:`accepted`,deliveryId:e.delivery.deliveryId}:{sessionId:t,status:`accepted`}}function inactiveCommandResult(e){return e.kind===`send`?{status:`session_not_active`}:e.kind===`cancel`?{status:`no_active_turn`}:{status:`no_active_session`}}async function dispatchWorkflowSessionCommand(e){let t={sessionId:e.sessionId};try{return await dispatchWorkflowCommand(t,e.command)}catch(n){if(!(n instanceof StrandedSessionOwnerError))throw n;return await settleStrandedCommand(t,e.command,n)}}async function isRunActive(e){try{let t=await getRun(e).status;return t===`pending`||t===`running`}catch(e){if(isInactiveCommandTarget(e))return!1;throw e}}function isInactiveCommandTarget(e){if(e instanceof AcceptedSessionIdentityError)return!1;if(HookNotFoundError.is(e))return!0;for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t)||RunExpiredError.is(t)||EntityConflictError.is(t))return!0;return!1}async function resolveContinuation(e){try{return await resolveSessionInbox(e)}catch(t){if(HookNotFoundError.is(t))return;throw logError(log,`failed to resolve session by continuation token`,t,{continuationToken:e}),t}}async function waitForCommandHookOwner(e){let t=await pollUntil(async()=>{try{return normalizeWorkflowHook(await getHookByToken(e))}catch(e){if(!HookNotFoundError.is(e))throw e;return}},SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(t===void 0)throw new HookNotFoundError(e);return t}async function waitForSessionInbox(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await pollUntil(async()=>await findSessionHookHolder(t)!==void 0||!await hasRunEnded(e)&&void 0,SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(n===void 0)throw Error(`Session "${e}" did not start taking commands within ${SESSION_HOOK_HANDOVER_TIMEOUT_MS/1e3} seconds.`);return n}async function pollUntil(e,t){let n=Date.now()+t;for(let t=20;;t=Math.min(t*2,200)){let r=await e();if(r!==void 0||Date.now()>=n)return r;await new Promise(e=>setTimeout(e,t))}}async function hasRunEnded(e){try{let t=await getRun(e).status;return t!==`pending`&&t!==`running`}catch(e){for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t))return!1;if(isInactiveCommandTarget(e))return!0;throw e}}async function startWorkflowOnCurrentDeployment(e,t,n){return await startWorkflowOnDeployment(e,t,await resolveCurrentWorkflowDeploymentId(),n)}async function startWorkflowOnDeployment(e,t,n,r){return await withWorkflowStartContext(async()=>{if(n.length===0||n===`latest`)throw Error(`Workflow starts require an exact deployment id.`);return await start(e,t,{...r,allowReservedAttributes:!0,attributes:{...r?.attributes,[EVE_VERSION_ATTRIBUTE]:EVE_PACKAGE_INFO.version},deploymentId:n})})}async function resolveCurrentWorkflowDeploymentId(){let e=process.env.VERCEL_DEPLOYMENT_ID?.trim()||await(await getWorld()).getDeploymentId();if(e.length===0||e===`latest`)throw Error(`Workflow runtime could not resolve an exact deployment id.`);return e}async function withWorkflowStartContext(e){let t=context.active(),n=isAgentTraceContext(t)?trace.deleteSpan(t):t;return await context.with(n,e)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}export{createWorkflowRuntime,dispatchWorkflowSessionCommand,hasRunEnded,pollUntil,resolveContinuation,sessionTimeoutWorkflowReference,startSessionOwnerStep,startWorkflowOnCurrentDeployment,waitForCommandHookOwner,waitForSessionInbox,workflowEntryReference,workflowToolRunWorkflowReference};
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{sessionCommandHookToken,sessionInboxHookToken}from"#execution/session-inbox/address.js";import{SessionPredecessorKey}from"#context/keys.js";import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{walkCauseChain}from"#shared/errors.js";import{validateToolStubTargets}from"#tool-stubs/validate-targets.js";import{getHookByToken,getRun,getWorld,start}from"#internal/workflow/runtime.js";import{SessionStrandedError,describeStrandedSession}from"#channel/session-stranded-error.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{ROOT_RUNTIME_AGENT_NODE_ID}from"#runtime/graph.js";import{serializeContext}from"#context/serialize.js";import{AcceptedSessionIdentityError,SessionHandoffPendingError,logicalSessionToken,resolveSessionInbox,resumeSessionInbox}from"#execution/session-inbox/resume.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{context,trace}from"#compiled/@opentelemetry/api/index.js";import{EntityConflictError,HookNotFoundError,RunExpiredError,WorkflowRunNotFoundError}from"#compiled/@workflow/errors/index.js";import{StrandedSessionOwnerError,assertRunnableSessionInbox,findSessionHookHolder}from"#execution/session-inbox/owner.js";import{initializeSessionInstrumentation}from"#instrumentation/runtime.js";import{EVE_VERSION_ATTRIBUTE,buildSessionAttributes,buildSubagentRootAttributes,readParentLineage}from"#execution/eve-workflow-attributes.js";import{endStrandedSession}from"#execution/session-inbox/end-stranded-session.js";import{SESSION_HOOK_HANDOVER_TIMEOUT_MS,waitForSessionHooksRelease}from"#execution/session-inbox/hook-release.js";import{CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME,CONNECTION_EVENT_WORKFLOW_NAME,SESSION_TIMEOUT_WORKFLOW_NAME,WORKFLOW_ENTRY_NAME,WORKFLOW_TOOL_RUN_WORKFLOW_NAME}from"#execution/stable-workflow-names.js";import{normalizeEveAttributes}from"#runtime/attributes/normalize.js";import{buildRunContext}from"#execution/runtime-context.js";import{readSessionEventHistory,readSessionEventStream,readSessionStreamTailIndex}from"#execution/session-event-stream.js";import{SESSION_HANDOFF_VERSION}from"#execution/session/entry-input.js";import{buildInvocationAttributes}from"#internal/invocation/metadata.js";import{isAgentTraceContext}from"#tracing/eve/agent-trace-context.js";const EVE_PACKAGE_INFO=resolveInstalledPackageInfo(),STABLE_ID_BASE=EVE_PACKAGE_INFO.name,log=createLogger(`execution.workflow-runtime`),workflowEntryReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_ENTRY_NAME}`},sessionTimeoutWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${SESSION_TIMEOUT_WORKFLOW_NAME}`},workflowToolRunWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${WORKFLOW_TOOL_RUN_WORKFLOW_NAME}`},connectionEventWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_WORKFLOW_NAME}`},connectionEventDeliveryWorkflowReference={workflowId:`workflow//${STABLE_ID_BASE}//${CONNECTION_EVENT_DELIVERY_WORKFLOW_NAME}`};function createWorkflowRuntime(e){let startSession=async(t,n)=>{let r=await getCompiledRuntimeAgentBundle({compiledArtifactsSource:e.compiledArtifactsSource,nodeId:e.nodeId});t.toolStubs!==void 0&&t.toolStubs.rootSessionId===void 0&&validateToolStubTargets(t.toolStubs.rules,r.graph);let i=buildRunContext({bundle:r,dynamicSubagentAgentConfig:e.dynamicSubagentAgentConfig,run:t});n!==void 0&&i.set(SessionPredecessorKey,n);let a=resolveEffectiveAgentRuntime(r,i),o=initializeSessionInstrumentation({agentName:a.turnAgent.id,ctx:i}),s=a.limits?.sessionTimeoutMs,c=r.resolvedAgent.config?.experimental?.workflow?.retention??(o.action===`record`&&o.recordInputs&&o.recordOutputs?void 0:0),l=serializeContext(i),u=readParentLineage(l),d={kind:`initial`,input:t.input,ownerDeploymentId:await resolveCurrentWorkflowDeploymentId(),serializedContext:l};t.limits!==void 0&&(d.limits=t.limits),t.continuationConflictCommand!==void 0&&(d.continuationConflictCommand=t.continuationConflictCommand),s!==void 0&&(d.sessionTimeoutMs=s),c!==void 0&&(d.retention=c);let f={...u.sessionId===void 0?buildSessionAttributes({serializedContext:l}):buildSubagentRootAttributes({identity:{nodeId:r.nodeId??ROOT_RUNTIME_AGENT_NODE_ID},parentCallId:u.callId,parentSessionId:u.sessionId,parentTurnId:u.turnId,rootSessionId:u.rootSessionId??u.sessionId,serializedContext:l}),...t.externalInvocation===void 0?{}:buildInvocationAttributes(t.externalInvocation)},p;try{let e={allowReservedAttributes:!0,attributes:normalizeEveAttributes(f)};c!==void 0&&(e.experimental_retention=c),p=await startWorkflowOnDeployment(workflowEntryReference,[d],d.ownerDeploymentId,e)}catch(e){throw logError(log,`failed to start workflow run`,e,{continuationToken:t.continuationToken}),e}let m,getEvents=()=>(m??=readSessionEventStream(p.runId),m);return{get events(){return getEvents()},sessionId:p.runId}};return{async createSession(e){return await startSession(e)},async dispatchContinuation(e){let{command:t,continuationToken:n,successor:r}=e;try{return await dispatchWorkflowCommand(n,t)}catch(e){if(!(e instanceof StrandedSessionOwnerError))throw e;if(t.kind!==`send`||r===void 0)return await settleStrandedCommand(n,t,e);if((t.payload.inputResponses?.length??0)>0)throw sessionStrandedError(e,`Its pending requests can no longer be answered; send a new message to start a fresh session.`);let i=await endStrandedSession(e,n,`message`);return{sessionId:(await startSession(r,{sessionId:i})).sessionId,status:`accepted`}}},async dispatchSession(e){return await dispatchWorkflowSessionCommand(e)},async getEventStream(e,t){if(t?.follow===!1)return readSessionEventHistory(e,t.startIndex);try{await assertRunnableSessionInbox(sessionInboxHookToken(sessionCommandHookToken(e)))}catch(e){throw e instanceof StrandedSessionOwnerError?sessionStrandedError(e):e}return readSessionEventStream(e,t?.startIndex)},async getStreamTailIndex(e){return await readSessionStreamTailIndex(e)},resolveContinuation}}async function startSessionOwnerStep(e){"use step";let{activationToken:t,anchorRunId:n,checkpoint:r,targetDeploymentId:i,...a}=e,o={...a,activationToken:t,checkpoint:r,handoffVersion:SESSION_HANDOFF_VERSION,kind:`handoff`,ownerDeploymentId:i,sessionWritable:getRun(n).getWritable(),sessionId:n};await startWorkflowOnDeployment(workflowEntryReference,[o],i,r.retention===void 0?void 0:{experimental_retention:r.retention})}async function dispatchWorkflowCommand(e,t){let n;try{let r=await resumeSessionInbox(e,t);n={runId:r.ownerRunId,sessionId:await r.sessionId}}catch(n){if(n instanceof StrandedSessionOwnerError)throw n;let r=t.kind===`send`&&typeof e!=`string`,i={status:`session_not_active`,retryable:!0};if(n instanceof SessionHandoffPendingError){if(r)return i;throw n}if(isInactiveCommandTarget(n))return r&&await isRunActive(e.sessionId)?i:inactiveCommandResult(t);throw logError(log,`failed to dispatch session command`,n,{command:t.kind,token:e}),n}return t.kind===`reset`&&await waitForSessionHooksRelease([sessionCommandHookToken(n.sessionId),logicalSessionToken(e)],n.runId),activeCommandResult(t,n.sessionId)}async function settleStrandedCommand(e,t,n){switch(t.kind){case`reset`:return{previousSessionId:await endStrandedSession(n,e,`reset`),status:`reset`};case`send`:case`clear`:throw sessionStrandedError(n);default:return inactiveCommandResult(t)}}function sessionStrandedError(e,t){let n=e.eveVersion===void 0?{}:{eveVersion:e.eveVersion};return new SessionStrandedError(n,describeStrandedSession(n,t))}function activeCommandResult(e,t){return e.kind===`reset`?{previousSessionId:t,status:`reset`}:e.kind===`send`&&e.delivery!==void 0?{sessionId:t,status:`accepted`,deliveryId:e.delivery.deliveryId}:{sessionId:t,status:`accepted`}}function inactiveCommandResult(e){return e.kind===`send`?{status:`session_not_active`}:e.kind===`cancel`?{status:`no_active_turn`}:{status:`no_active_session`}}async function dispatchWorkflowSessionCommand(e){let t={sessionId:e.sessionId};try{return await dispatchWorkflowCommand(t,e.command)}catch(n){if(!(n instanceof StrandedSessionOwnerError))throw n;return await settleStrandedCommand(t,e.command,n)}}async function isRunActive(e){try{let t=await getRun(e).status;return t===`pending`||t===`running`}catch(e){if(isInactiveCommandTarget(e))return!1;throw e}}function isInactiveCommandTarget(e){if(e instanceof AcceptedSessionIdentityError)return!1;if(HookNotFoundError.is(e))return!0;for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t)||RunExpiredError.is(t)||EntityConflictError.is(t))return!0;return!1}async function resolveContinuation(e){try{return await resolveSessionInbox(e)}catch(t){if(HookNotFoundError.is(t))return;throw logError(log,`failed to resolve session by continuation token`,t,{continuationToken:e}),t}}async function waitForCommandHookOwner(e){let t=await pollUntil(async()=>{try{return normalizeWorkflowHook(await getHookByToken(e))}catch(e){if(!HookNotFoundError.is(e))throw e;return}},SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(t===void 0)throw new HookNotFoundError(e);return t}async function waitForSessionInbox(e){let t=sessionInboxHookToken(sessionCommandHookToken(e)),n=await pollUntil(async()=>await findSessionHookHolder(t)!==void 0||!await hasRunEnded(e)&&void 0,SESSION_HOOK_HANDOVER_TIMEOUT_MS);if(n===void 0)throw Error(`Session "${e}" did not start taking commands within ${SESSION_HOOK_HANDOVER_TIMEOUT_MS/1e3} seconds.`);return n}async function pollUntil(e,t){let n=Date.now()+t;for(let t=20;;t=Math.min(t*2,200)){let r=await e();if(r!==void 0||Date.now()>=n)return r;await new Promise(e=>setTimeout(e,t))}}async function hasRunEnded(e){try{let t=await getRun(e).status;return t!==`pending`&&t!==`running`}catch(e){for(let t of walkCauseChain(e))if(WorkflowRunNotFoundError.is(t))return!1;if(isInactiveCommandTarget(e))return!0;throw e}}async function startWorkflowOnCurrentDeployment(e,t,n){return await startWorkflowOnDeployment(e,t,await resolveCurrentWorkflowDeploymentId(),n)}async function startWorkflowOnDeployment(e,t,n,r){return await withWorkflowStartContext(async()=>{if(n.length===0||n===`latest`)throw Error(`Workflow starts require an exact deployment id.`);return await start(e,t,{...r,allowReservedAttributes:!0,attributes:{...r?.attributes,[EVE_VERSION_ATTRIBUTE]:EVE_PACKAGE_INFO.version},deploymentId:n})})}async function resolveCurrentWorkflowDeploymentId(){let e=process.env.VERCEL_DEPLOYMENT_ID?.trim()||await(await getWorld()).getDeploymentId();if(e.length===0||e===`latest`)throw Error(`Workflow runtime could not resolve an exact deployment id.`);return e}async function withWorkflowStartContext(e){let t=context.active(),n=isAgentTraceContext(t)?trace.deleteSpan(t):t;return await context.with(n,e)}function normalizeWorkflowHook(e){if(typeof e!=`object`||!e||!(`runId`in e))throw Error(`Workflow hook did not include a run id.`);let t=e.runId;if(typeof t!=`string`||t.length===0)throw Error(`Workflow hook did not include a run id.`);return{runId:t}}export{connectionEventDeliveryWorkflowReference,connectionEventWorkflowReference,createWorkflowRuntime,dispatchWorkflowSessionCommand,hasRunEnded,pollUntil,resolveContinuation,sessionTimeoutWorkflowReference,startSessionOwnerStep,startWorkflowOnCurrentDeployment,waitForCommandHookOwner,waitForSessionInbox,workflowEntryReference,workflowToolRunWorkflowReference};
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import type { GitHubConfig } from "./lib/github-shell.ts";
|
|
2
|
+
import type { GitHubAuthorize, GitHubConfig } from "./lib/github-shell.ts";
|
|
3
3
|
export type { GitHubLeaseRule } from "./lib/github-shell.ts";
|
|
4
|
+
export type { GitHubAuthorize, GitHubAuthorizeRequest } from "./lib/github-shell.ts";
|
|
4
5
|
export type GitHubLeaseBroker = GitHubConfig["broker"];
|
|
5
6
|
declare const _default: import("eve/extension").ExtensionHandle<z.ZodObject<{
|
|
6
7
|
github: z.ZodOptional<z.ZodObject<{
|
|
7
8
|
connector: z.ZodString;
|
|
8
9
|
org: z.ZodString;
|
|
9
10
|
broker: z.ZodCustom<(sandbox: import("../../../shared/sandbox-session.ts").SandboxSession, rules: Readonly<Record<string, readonly import("./lib/github-shell.ts").GitHubLeaseRule[]>> | null) => Promise<void>, (sandbox: import("../../../shared/sandbox-session.ts").SandboxSession, rules: Readonly<Record<string, readonly import("./lib/github-shell.ts").GitHubLeaseRule[]>> | null) => Promise<void>>;
|
|
11
|
+
authorize: z.ZodOptional<z.ZodCustom<GitHubAuthorize, GitHubAuthorize>>;
|
|
10
12
|
}, z.core.$strip>>;
|
|
11
13
|
}, z.core.$strip>>;
|
|
12
14
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z}from"#compiled/zod/index.js";import{defineExtension}from"eve/extension";var extension_default=defineExtension({config:z.object({github:z.object({connector:z.string().min(1),org:z.string().min(1),broker:
|
|
1
|
+
import{z}from"#compiled/zod/index.js";import{defineExtension}from"eve/extension";const fn=()=>z.custom(e=>typeof e==`function`);var extension_default=defineExtension({config:z.object({github:z.object({connector:z.string().min(1),org:z.string().min(1),broker:fn(),authorize:fn().optional()}).optional()})});export{extension_default as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{executeGitHubShell,githubShellApproval}from"./github-shell.js";import{githubShellInputSchema}from"./github-shell-schema.js";import{z}from"#compiled/zod/index.js";import{defineTool}from"eve/tools";const GH_TOOL_DESCRIPTION=`Run one authenticated GitHub command in the sandbox. The full gh CLI surface is available. Commands run without an approval prompt; description records the GitHub-side result the command intends to produce. Declare exactly one repository in the configured GitHub organization: Connect mints the real token for only that repository, and the sandbox process receives only a placeholder GH_TOKEN that the firewall exchanges on matching GitHub requests. GitHub rejects access outside the token's server-side repository scope; commands that explicitly name another repository with -R, --repo, --repo=, or a repository argument to gh repo clone, view, or fork are denied before minting. Use simple argv quoting only, never environment assignments, pipes, redirects, substitutions, or other shell syntax. gh alias and extension commands may execute local code, but remain sandboxed. Use git here only for authenticated fetch, pull, push, or ls-remote against a strictly validated origin, and use gh-signed-commit only with --repo. Use ordinary bash for local git status, diff, add, commit, and rebase.`;function defineGhTool(e,t=GH_TOOL_DESCRIPTION){return defineTool({description:t,approval:({toolInput:e})=>githubShellApproval(e),inputSchema:githubShellInputSchema,outputSchema:z.object({exitCode:z.number().int(),stderr:z.string(),stdout:z.string(),truncated:z.boolean()}),execute(t,n){return executeGitHubShell(t,e(),{getSandbox:()=>n.getSandbox(),sessionId:n.session.id})}})}export{GH_TOOL_DESCRIPTION,defineGhTool};
|
|
1
|
+
import{executeGitHubShell,githubShellApproval}from"./github-shell.js";import{githubShellInputSchema}from"./github-shell-schema.js";import{z}from"#compiled/zod/index.js";import{defineTool}from"eve/tools";const GH_TOOL_DESCRIPTION=`Run one authenticated GitHub command in the sandbox. The full gh CLI surface is available. Commands run without an approval prompt; description records the GitHub-side result the command intends to produce. Declare exactly one repository in the configured GitHub organization: Connect mints the real token for only that repository, and the sandbox process receives only a placeholder GH_TOKEN that the firewall exchanges on matching GitHub requests. GitHub rejects access outside the token's server-side repository scope; commands that explicitly name another repository with -R, --repo, --repo=, or a repository argument to gh repo clone, view, or fork are denied before minting. Use simple argv quoting only, never environment assignments, pipes, redirects, substitutions, or other shell syntax. gh alias and extension commands may execute local code, but remain sandboxed. Use git here only for authenticated fetch, pull, push, or ls-remote against a strictly validated origin, and use gh-signed-commit only with --repo. Use ordinary bash for local git status, diff, add, commit, and rebase.`;function defineGhTool(e,t=GH_TOOL_DESCRIPTION){return defineTool({description:t,approval:({toolInput:e})=>githubShellApproval(e),inputSchema:githubShellInputSchema,outputSchema:z.object({exitCode:z.number().int(),stderr:z.string(),stdout:z.string(),truncated:z.boolean()}),execute(t,n){return executeGitHubShell(t,e(),{auth:n.session.auth.current,getSandbox:()=>n.getSandbox(),sessionId:n.session.id})}})}export{GH_TOOL_DESCRIPTION,defineGhTool};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getToken } from "@vercel/connect";
|
|
2
|
+
import type { SessionAuthContext } from "eve/context";
|
|
2
3
|
import type { SandboxSession } from "eve/sandbox";
|
|
3
4
|
export interface GitHubPermission {
|
|
4
5
|
readonly access: "write";
|
|
@@ -18,10 +19,22 @@ export interface GitHubShellOutput {
|
|
|
18
19
|
readonly truncated: boolean;
|
|
19
20
|
}
|
|
20
21
|
export interface GitHubConfig {
|
|
22
|
+
readonly authorize?: GitHubAuthorize;
|
|
21
23
|
readonly broker: (sandbox: SandboxSession, rules: Readonly<Record<string, readonly GitHubLeaseRule[]>> | null) => Promise<void>;
|
|
22
24
|
readonly connector: string;
|
|
23
25
|
readonly org: string;
|
|
24
26
|
}
|
|
27
|
+
/** What an `authorize` callback sees before a `gh` command runs. */
|
|
28
|
+
export interface GitHubAuthorizeRequest {
|
|
29
|
+
/** The session's current caller, or `null` when the session has none. */
|
|
30
|
+
readonly auth: SessionAuthContext | null;
|
|
31
|
+
/** The `owner/name` repository the command declared. */
|
|
32
|
+
readonly repository: string;
|
|
33
|
+
/** The repository-scoped GitHub App token minted for this command, for API lookups. */
|
|
34
|
+
readonly token: string;
|
|
35
|
+
}
|
|
36
|
+
/** Decides whether the session's caller may run a `gh` command against one repository. */
|
|
37
|
+
export type GitHubAuthorize = (request: GitHubAuthorizeRequest) => boolean | Promise<boolean>;
|
|
25
38
|
export interface GitHubLeaseRule {
|
|
26
39
|
readonly match?: {
|
|
27
40
|
readonly headers?: readonly {
|
|
@@ -39,6 +52,7 @@ export interface GitHubLeaseRule {
|
|
|
39
52
|
}[];
|
|
40
53
|
}
|
|
41
54
|
interface GitHubShellDependencies {
|
|
55
|
+
readonly auth?: SessionAuthContext | null;
|
|
42
56
|
readonly getConnectToken?: typeof getToken;
|
|
43
57
|
readonly getSandbox: () => Promise<SandboxSession>;
|
|
44
58
|
/** Serializes credential leases per eve session; every `ctx.getSandbox()` call returns a new handle. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{shellQuote}from"./shell.js";import{validateRepositoryRoot}from"./repository-root.js";import{GITHUB_TOOLING_PATHS}from"./tooling.js";import{posix}from"node:path";import{getToken}from"#compiled/@vercel/connect/index.js";const MAX_OUTPUT_BYTES=1e5,leaseQueues=new Map,ALLOWED_GIT_REMOTE_COMMANDS=new Set([`fetch`,`ls-remote`,`pull`,`push`]);function githubShellApproval(e){if(!e)return`not-applicable`;try{return validateGitHubShellInput(e),`not-applicable`}catch(e){return{type:`denied`,reason:e instanceof Error?e.message:`Invalid GitHub command.`}}}async function executeGitHubShell(e,t,n){if(!t)throw Error(`GitHub command access is not configured for this agent.`);let r=validateGitHubShellInput(e),i=await n.getSandbox(),a=resolveWorkingDirectory(i,e.workingDirectory);(r[0]===`git`||r[0]===`gh-signed-commit`)&&(a=await validateRepositoryRoot(i,a));let o=e.permissions[0].repositories,s=await assertCommandTargets(r,o,a,i),c=repositoryNames(o,t.org),l={authorizationDetails:[{type:`github_app_installation`,org:t.org,repositories:c}],subject:{type:`app`}},u=await(n.getConnectToken??getToken)(t.connector,l);if(!u)throw Error(`Connect returned an empty token for ${JSON.stringify(t.connector)}.`);let d=executablePath(r[0]),
|
|
1
|
+
import{shellQuote}from"./shell.js";import{validateRepositoryRoot}from"./repository-root.js";import{GITHUB_TOOLING_PATHS}from"./tooling.js";import{posix}from"node:path";import{getToken}from"#compiled/@vercel/connect/index.js";const MAX_OUTPUT_BYTES=1e5,leaseQueues=new Map,ALLOWED_GIT_REMOTE_COMMANDS=new Set([`fetch`,`ls-remote`,`pull`,`push`]);function githubShellApproval(e){if(!e)return`not-applicable`;try{return validateGitHubShellInput(e),`not-applicable`}catch(e){return{type:`denied`,reason:e instanceof Error?e.message:`Invalid GitHub command.`}}}async function executeGitHubShell(e,t,n){if(!t)throw Error(`GitHub command access is not configured for this agent.`);let r=validateGitHubShellInput(e),i=await n.getSandbox(),a=resolveWorkingDirectory(i,e.workingDirectory);(r[0]===`git`||r[0]===`gh-signed-commit`)&&(a=await validateRepositoryRoot(i,a));let o=e.permissions[0].repositories,s=await assertCommandTargets(r,o,a,i),c=repositoryNames(o,t.org),l={authorizationDetails:[{type:`github_app_installation`,org:t.org,repositories:c}],subject:{type:`app`}},u=await(n.getConnectToken??getToken)(t.connector,l);if(!u)throw Error(`Connect returned an empty token for ${JSON.stringify(t.connector)}.`);let d=o[0];if(t.authorize&&!await t.authorize({auth:n.auth??null,repository:d,token:u}))throw Error(`The current caller is not authorized to access ${d}.`);let f=executablePath(r[0]),p=s?[`-c`,`protocol.allow=never`,`-c`,`protocol.https.allow=always`,r[1],`https://github.com/${s}.git`,...r.slice(3)]:r.slice(1),m=`cd ${shellQuote(a)} && exec ${shellQuote(f)} ${p.map(shellQuote).join(` `)}`,h=`Basic ${Buffer.from(`x-access-token:${u}`).toString(`base64`)}`,g=crypto.randomUUID(),_=`eve-github-${g}`,v=`/tmp/eve-code-gh-${g}`,y=`Basic ${Buffer.from(`x-access-token:${_}`).toString(`base64`)}`,b;try{b=await withGitHubCredentialLease(i,n.sessionId,{authorization:h,placeholder:_,placeholderAuthorization:y,token:u},()=>{let e={GH_CONFIG_DIR:v,GH_PROMPT_DISABLED:`1`};return r[0]!==`git`&&(e.GH_TOKEN=_),e.GIT_CONFIG_COUNT=`2`,e.GIT_CONFIG_KEY_0=`http.https://github.com/.extraheader`,e.GIT_CONFIG_VALUE_0=`Authorization: ${y}`,e.GIT_CONFIG_KEY_1=`core.hooksPath`,e.GIT_CONFIG_VALUE_1=`/dev/null`,e.GIT_TERMINAL_PROMPT=`0`,e.PATH=`/usr/local/bin:/usr/bin:/bin`,i.run({command:m,env:e})},t.broker)}finally{await i.removePath({path:v,recursive:!0,force:!0})}let x=sanitizeOutput(b.stdout,u,h),S=sanitizeOutput(b.stderr,u,h);return{exitCode:b.exitCode,stdout:x.value,stderr:S.value,truncated:x.truncated||S.truncated}}async function withGitHubCredentialLease(e,t,n,r,i){let a=leaseQueues.get(t)??Promise.resolve(),o,s=new Promise(e=>{o=e}),c=a.then(()=>s);leaseQueues.set(t,c),await a;try{return await i(e,{"api.github.com":[{match:{headers:[{key:{exact:`authorization`},value:{regex:`^(?:token|Bearer) ${n.placeholder}$`}}]},transform:[{headers:{authorization:`Bearer ${n.token}`}}]}],"github.com":[{match:{headers:[{key:{exact:`authorization`},value:{exact:n.placeholderAuthorization}}]},transform:[{headers:{authorization:n.authorization}}]}]}),await r()}finally{try{await i(e,null)}finally{o(),leaseQueues.get(t)===c&&leaseQueues.delete(t)}}}function parseCommand(e){let t=e.trim();if(!t)throw Error(`GitHub command must not be empty.`);let n=[],r=``,i=null,a=!1,o=!1;for(let e of t){if(a){r+=e,a=!1,o=!0;continue}if(e===`\\`&&i!==`single`){a=!0,o=!0;continue}if(i===`single`){e===`'`?i=null:r+=e;continue}if(i===`double`){if(e===`"`)i=null;else if(e===`$`||e==="`")throw unsupportedSyntax();else r+=e;continue}if(e===`'`)i=`single`,o=!0;else if(e===`"`)i=`double`,o=!0;else if(/\s/u.test(e))o&&=(n.push(r),r=``,!1);else if(";&|<>$`(){}".includes(e))throw unsupportedSyntax();else r+=e,o=!0}if(a||i)throw Error(`GitHub command contains an unfinished quote or escape.`);if(o&&n.push(r),n.length===0)throw Error(`GitHub command must not be empty.`);return n}function validateGitHubShellInput(e){let t=parseCommand(e.command),n=e.permissions[0];if(e.permissions.length!==1||n?.provider!==`github`)throw Error(`Exactly one GitHub permission is required.`);if(n.access!==`write`)throw Error(`GitHub App commands require explicit write-capable access.`);if(!e.description.trim())throw Error(`description must describe the intended result.`);let[r,i]=t;if(r===`gh`){if(!i)throw Error(`A gh subcommand is required.`)}else if(r===`git`){if(!i||!ALLOWED_GIT_REMOTE_COMMANDS.has(i))throw Error(`Authenticated git supports only fetch, ls-remote, pull, and push; clone with gh repo clone.`)}else if(r!==`gh-signed-commit`)throw Error(`GitHub commands must use gh, an authenticated git remote command, or gh-signed-commit.`);return t}async function assertCommandTargets(e,t,n,r){let i=new Set(t.map(e=>e.toLowerCase())),a,o;if(e[0]===`git`){if(e[2]!==`origin`)throw Error(`Authenticated git commands must use the validated origin remote.`);let t=e[1]===`push`,i=await r.run({command:`cd ${shellQuote(n)} && git remote get-url ${t?`--push `:``}origin`,env:{GIT_TERMINAL_PROMPT:`0`,PATH:`/usr/bin:/bin`}});if(i.exitCode!==0)throw Error(`Could not resolve the origin GitHub repository.`);a=repositoryFromRemote(i.stdout.trim()),o=[a]}else if(e[0]===`gh-signed-commit`){if(o=repoFlagTargets(e.slice(1)),o.length===0)throw Error(`gh-signed-commit requires an explicit --repo owner/repository target.`)}else o=repoFlagTargets(e.slice(1)),e[1]===`repo`&&(e[2]===`clone`||e[2]===`view`||e[2]===`fork`)&&e[3]&&!e[3].startsWith(`-`)&&o.push(canonicalRepository(e[3]));for(let e of o)if(!i.has(e.toLowerCase()))throw Error(`Command target ${JSON.stringify(e)} is not in the declared repositories.`);return a}function repoFlagTargets(e){let t=[];for(let n=0;n<e.length;n+=1){let r=e[n];if(r===`--repo`||r===`-R`){let i=e[n+1];if(!i)throw Error(`${r} requires an owner/repository value.`);t.push(canonicalRepository(i)),n+=1}else r?.startsWith(`--repo=`)&&t.push(canonicalRepository(r.slice(7)))}return t}function repositoryFromRemote(e){let t=/^https:\/\/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/iu.exec(e);if(t?.[1])return canonicalRepository(t[1]);let n=/^git@github\.com:([^/]+\/[^/]+?)(?:\.git)?$/iu.exec(e);if(n?.[1])return canonicalRepository(n[1]);throw Error(`The origin remote is not a canonical GitHub repository URL.`)}function canonicalRepository(e){let t=e.replace(/\.git$/iu,``);if(!/^[A-Za-z0-9-]+\/[A-Za-z0-9._-]+$/u.test(t))throw Error(`Invalid GitHub repository ${JSON.stringify(e)}.`);return t}function repositoryNames(e,t){if(e.length!==1)throw Error(`Exactly one GitHub repository is required.`);let n=new Set;for(let r of e){let e=/^([A-Za-z0-9-]+)\/([A-Za-z0-9._-]+)$/u.exec(r);if(!e)throw Error(`Invalid GitHub repository ${JSON.stringify(r)}.`);if(e[1]?.toLowerCase()!==t.toLowerCase())throw Error(`Repository ${JSON.stringify(r)} is outside ${t}.`);n.add(e[2])}if(n.size!==1)throw Error(`Exactly one GitHub repository is required.`);return[...n]}function executablePath(e){return e===`gh`?GITHUB_TOOLING_PATHS.ghReal:e===`gh-signed-commit`?GITHUB_TOOLING_PATHS.trustedSignedCommit:`git`}function resolveWorkingDirectory(e,t){let n=posix.resolve(`/`,e.resolvePath(``)),r=posix.resolve(`/`,e.resolvePath(t?.trim()||``));if(r!==n&&!r.startsWith(`${n}/`))throw Error(`GitHub command workingDirectory must stay inside the sandbox workspace.`);return r}function sanitizeOutput(e,t,n){let r=e.replaceAll(t,`[redacted]`).replaceAll(n,`[redacted]`);return Buffer.byteLength(r)<=MAX_OUTPUT_BYTES?{value:r,truncated:!1}:{value:`[output truncated: showing final ${MAX_OUTPUT_BYTES} bytes]\n${Buffer.from(r).subarray(-1e5).toString()}`,truncated:!0}}function unsupportedSyntax(){return Error(`GitHub commands support argv syntax only, not pipes, redirects, substitutions, or shell operators.`)}export{executeGitHubShell,githubShellApproval,parseCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{skillTarget}from"#shared/action-request-name.js";import{toError}from"#shared/errors.js";import{SKILL_ENTRY_NAME}from"#protocol/catalog-tools.js";import{parseJsonValue}from"#shared/json.js";import{authorizationPendingAsJsonObject,isAuthorizationPendingModelOutput,isAuthorizationSignal}from"#harness/authorization.js";import{withToolOutputSerializationError}from"#harness/tool-output-serialization.js";function toJsonValue(e){return isAuthorizationSignal(e)?parseJsonValue(authorizationPendingAsJsonObject({connections:e.challenges.map(e=>e.name)})):isAuthorizationPendingModelOutput(e)?parseJsonValue(authorizationPendingAsJsonObject(e)):parseJsonValue(e===void 0?null:e)}function createRuntimeToolResultFromValue(e){let t={callId:e.callId,kind:`tool-result`,output:toolResultOutputToJsonValue({output:{type:e.isError===!0?`error-json`:`json`,value:
|
|
1
|
+
import{skillTarget}from"#shared/action-request-name.js";import{toError}from"#shared/errors.js";import{SKILL_ENTRY_NAME}from"#protocol/catalog-tools.js";import{parseJsonValue}from"#shared/json.js";import{authorizationPendingAsJsonObject,isAuthorizationPendingModelOutput,isAuthorizationSignal}from"#harness/authorization.js";import{withToolOutputSerializationError}from"#harness/tool-output-serialization.js";function toJsonValue(e){return isAuthorizationSignal(e)?parseJsonValue(authorizationPendingAsJsonObject({connections:e.challenges.map(e=>e.name)})):isAuthorizationPendingModelOutput(e)?parseJsonValue(authorizationPendingAsJsonObject(e)):parseJsonValue(e===void 0?null:e)}function createRuntimeToolResultFromValue(e){let t=e.isError===!0&&e.output instanceof Error?e.output:void 0,n={callId:e.callId,kind:`tool-result`,output:toolResultOutputToJsonValue({output:{type:e.isError===!0?`error-json`:`json`,value:t===void 0?e.output:t.message},toolCallId:e.callId,toolName:e.toolName}),toolName:e.toolName};return e.isError===!0?t===void 0?{...n,isError:!0}:{...n,errorName:t.name,isError:!0}:n}function createRuntimeToolResultFromStepResult(e){return createRuntimeToolResultFromValue({callId:e.toolCallId,output:e.output,toolName:e.toolName})}function createRuntimeToolResultFromToolError(e){return createRuntimeToolResultFromValue({callId:e.toolCallId,isError:!0,output:toError(e.error),toolName:e.toolName})}function toActionResult(e,t){let n=e.toolName===SKILL_ENTRY_NAME?skillTarget(t):void 0;return n===void 0?e:{callId:e.callId,isError:e.isError,kind:`load-skill-result`,name:n,output:e.output}}function createToolResultMessagePartFromToolError(e){return{type:`tool-result`,toolCallId:e.toolCallId,toolName:e.toolName,output:{type:`error-text`,value:toError(e.error).message}}}function createRuntimeToolResultFromMessagePart(e,t){return createRuntimeToolResultFromValue({callId:e.toolCallId,output:toolResultOutputToJsonValue({output:e.output,toolCallId:e.toolCallId,toolName:t}),toolName:t,isError:isToolResultError(e.output)})}function toolResultOutputToJsonValue(e){return withToolOutputSerializationError({boundary:`action.result`,toolCallId:e.toolCallId,toolName:e.toolName},()=>{switch(e.output.type){case`text`:case`error-text`:return e.output.value;case`json`:case`error-json`:return toJsonValue(e.output.value);case`execution-denied`:return{code:`TOOL_EXECUTION_DENIED`,message:e.output.reason??`Tool execution was denied.`};case`content`:return toJsonValue(e.output.value)}})}function isToolResultError(e){return e.type===`error-json`||e.type===`error-text`||e.type===`execution-denied`}export{createRuntimeToolResultFromMessagePart,createRuntimeToolResultFromStepResult,createRuntimeToolResultFromToolError,createRuntimeToolResultFromValue,createToolResultMessagePartFromToolError,isToolResultError,toActionResult};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash}from"node:crypto";import{buildSessionHandle}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{contextStorage,loadContext}from"#context/container.js";import{SandboxKey}from"#context/keys.js";import{deserializeUrlFilePart,isSerializedUrlFilePart}from"#internal/attachments/url-refs.js";import{basename,dirname,extname}from"node:path";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createFrameworkUserMessage}from"#harness/messages.js";import{DEFAULT_UPLOAD_POLICY,isMediaTypeAllowed}from"#public/channels/upload-policy.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{readMediaMetadata,verifyMediaType}from"#internal/attachments/media-metadata.js";import{decodeSandboxRef,encodeSandboxRef,inlinesSandboxRefAsBytes,isSandboxRefUrl}from"#internal/attachments/sandbox-refs.js";import{isUnresolvedFileData,readFileData}from"#internal/attachments/data.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{maxBytesOf}from"#internal/attachments/limited-read.js";import{createPublicDownloads}from"#internal/attachments/public-link.js";const ATTACHMENTS_ROOT=`/workspace/.eve/attachments`,log=createLogger(`harness.attachment-staging`),UNSAFE_FILENAME_CHARS=/[^\w.-]+/g,MEDIA_TYPE_EXTENSIONS={"application/pdf":`.pdf`,"image/gif":`.gif`,"image/jpeg":`.jpg`,"image/png":`.png`,"image/webp":`.webp`};async function stageAttachmentsForAdapter(e,t,n){if(typeof e==`string`)return e;let r=reconstitueFilePartUrls(e),i=n.ctx.get(ChannelKey)?.uploadPolicy,a=createPublicDownloads(maxBytesOf(i??DEFAULT_UPLOAD_POLICY));return Promise.all(r.map(async e=>e.type===`file`?stageFilePart(e,t,n,a,i):e))}async function stageAttachmentsToSandbox(e){if(typeof e==`string`||!Array.isArray(e)||!hasFileParts(e))return e;let t=loadContext(),n=await t.get(SandboxKey)?.get()??null;if(n===null)return e.map(e=>e.type===`file`&&!isSandboxRefUrl(e.data)&&readFileData(e.data).kind!==`reference`?attachmentNote(e,`could not be stored: no sandbox is available.`):e);let r=t.get(ChannelKey);return stageAttachmentsForAdapter(e,n,r?buildAdapterContext(r,t):{ctx:t,state:{},session:buildSessionHandle(t)})}async function stageToolResultMedia(e){if(!e.some(hasInlineToolResultFile))return[...e];let t=await contextStorage.getStore()?.get(SandboxKey)?.get()??null;return Promise.all(e.map(async e=>{if(e.role!==`tool`||!hasInlineToolResultFile(e))return e;let n=await Promise.all(e.content.map(async e=>e.type===`tool-result`?{...e,output:await stageToolOutputFiles(e.output,t)}:e));return{...e,content:n}}))}async function hydrateSandboxAttachments(e){let t=replaceUnresolvedFileParts(e);if(!messagesContainSandboxRef(t))return t;let n=loadContext().get(SandboxKey);if(n===void 0)throw Error(`Cannot hydrate sandbox-ref FilePart: no SandboxKey is bound on the active eve context. Hydration must run inside a step scope with the framework sandbox provider installed.`);let r=await n.get();if(r===null)throw Error(`Cannot hydrate sandbox-ref FilePart: SandboxKey is bound but no active sandbox session is available.`);return Promise.all(t.map(async e=>{if(!messageContainsSandboxRef(e))return e;let t=await hydrateMessageContent(e.content,r);return{...e,content:t}}))}function replaceUnresolvedFileParts(e){let t=!1,n=e.map(e=>{if(e.role!==`user`||!Array.isArray(e.content)||!e.content.some(isUnresolvedFilePart))return e;t=!0;let n=e.content.map(e=>isUnresolvedFilePart(e)?attachmentNote(e,`could not be retrieved.`):e);return{...e,content:n}});return t?n:e}function isUnresolvedFilePart(e){return e.type===`file`&&!isSandboxRefUrl(e.data)&&isUnresolvedFileData(e.data)}function hasFileParts(e){for(let t of e)if(t.type===`file`)return!0;return!1}function messagesContainSandboxRef(e){for(let t of e)if(messageContainsSandboxRef(t))return!0;return!1}function messageContainsSandboxRef(e){let t=e.content;if(!Array.isArray(t))return!1;for(let e of t)if(isSandboxRefFilePart(e)||e.type===`tool-result`&&contentOutputParts(e.output).some(isToolOutputRefFile))return!0;return!1}function contentOutputParts(e){return e.type===`content`?e.value:[]}function hasInlineToolResultFile(e){return e.role===`tool`&&e.content.some(e=>e.type===`tool-result`&&contentOutputParts(e.output).some(isInlineToolOutputFile))}function isInlineToolOutputFile(e){return e.type===`file`&&e.data.type===`data`}function isToolOutputRefFile(e){return e.type===`file`&&e.data.type===`url`&&isSandboxRefUrl(e.data.url)}async function stageToolOutputFiles(e,t){if(e.type!==`content`||!e.value.some(isInlineToolOutputFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isInlineToolOutputFile(e)||e.data.type!==`data`)return e;let n=readFileData(e.data.data);if(n.kind===`link`)return e;if(t===null||n.kind!==`bytes`)return{text:`Returned file ${e.filename??`file`} (${e.mediaType}) could not be stored.`,type:`text`};let r=await writeSandboxRef(n.bytes,e.mediaType,e.filename,t);return{...e,data:{type:`url`,url:encodeSandboxRef(r)},mediaType:r.mediaType}}));return{...e,value:n}}function isSandboxRefFilePart(e){return typeof e==`object`&&!!e&&e.type===`file`&&isSandboxRefUrl(e.data)}async function hydrateMessageContent(e,t){return Array.isArray(e)?(await Promise.all(e.map(async e=>{if(isSandboxRefFilePart(e)){let n=decodeSandboxRef(e.data),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await readSandboxRefBytes(n,t);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:i,mediaType:n.mediaType}]}if(e.type===`tool-result`){let n=e;return[{...n,output:await hydrateToolOutput(n.output,t)}]}return[e]}))).flat():e}async function hydrateToolOutput(e,t){if(e.type!==`content`||!e.value.some(isToolOutputRefFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isToolOutputRefFile(e)||e.data.type!==`url`)return[e];let n=decodeSandboxRef(e.data.url),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await readSandboxRefBytes(n,t);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:{data:Buffer.from(i).toString(`base64`),type:`data`}}]}));return{...e,value:n.flat()}}async function readSandboxRefBytes(e,t){let n=await t.readBinaryFile({path:e.path});return n===null?(log.warn(`sandbox-ref attachment bytes missing on hydration — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n.byteLength!==e.size||sha256Prefix(n)!==basename(dirname(e.path))?(log.warn(`sandbox-ref attachment bytes changed since staging — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n}function renderMissingSandboxRef(e){return{text:`FileNotFound: Current snapshot may be newer and does not contain ${e.path}.`,type:`text`}}function moveToolResultFilesToUserMessages(e){let t=[],n=[];for(let r of e){if(r.role!==`tool`&&n.length>0&&(t.push(createReturnedFilesMessage(n)),n=[]),r.role!==`tool`){t.push(r);continue}let e=r.content.map(e=>{if(e.type!==`tool-result`||e.output.type!==`content`)return e;let t=e.output.value.map(e=>{if(e.type!==`file`)return e;let t={data:e.data,mediaType:e.mediaType,type:`file`};return e.filename!==void 0&&(t.filename=e.filename),n.push(t),{text:`Attached file ${e.filename??`file`} (${e.mediaType}) follows this tool result.`,type:`text`}});return{...e,output:{...e.output,value:t}}});t.push({...r,content:e})}return n.length>0&&t.push(createReturnedFilesMessage(n)),t}function createReturnedFilesMessage(e){return createFrameworkUserMessage(`context.state`,[{text:`Files returned by the preceding tool results:`,type:`text`},...e])}function renderSandboxRefAsTextPart(e){return{text:`Attached file ${e.path} (${e.mediaType})`,type:`text`}}async function stageFilePart(e,t,n,r,i){if(isSandboxRefUrl(e.data))return e;let a=readFileData(e.data);if(a.kind===`bytes`)return stageResolvedBytes(e,{bytes:a.bytes},t,i);if(a.kind===`reference`)return e;if(a.kind===`unreadable`)return log.warn(`attachment data is not bytes, base64, or a URL — degrading to text part`,{filename:e.filename,mediaType:e.mediaType}),attachmentNote(e,`could not be read.`);let o;try{o=await resolveLink(a.url,n,r)}catch(t){if(!(t instanceof EveAttachmentError))throw t;return log.warn(`attachment resolver failed — degrading to text part`,{adapterKind:t.adapterKind,error:t.cause,filename:e.filename,kind:t.kind}),attachmentNote(e,`could not be retrieved: ${t.message}`)}return stageResolvedBytes(e,o,t,i)}function attachmentNote(e,t){return{text:`Attachment ${e.filename?.trim()||`file`} ${t}`,type:`text`}}async function stageResolvedBytes(e,t,n,r){let i=verifyMediaType(t.bytes,t.mediaType??e.mediaType??`application/octet-stream`);if(r!==void 0){let n=maxBytesOf(r);if(t.bytes.byteLength>n)return attachmentNote(e,`was not accepted: it is ${t.bytes.byteLength} bytes, over this channel's ${n}-byte upload limit.`);if(!isMediaTypeAllowed(i,r))return attachmentNote(e,`was not accepted: this channel doesn't accept ${i} files.`)}let a=await writeSandboxRef(t.bytes,i,t.filename??e.filename,n);return{...e,data:encodeSandboxRef(a),filename:a.path,mediaType:a.mediaType}}async function writeSandboxRef(e,t,n,r){let i=verifyMediaType(e,t),a=sha256Prefix(e),o=`${ATTACHMENTS_ROOT}/${a}/${safeFilename(n,a,i)}`;return await r.writeBinaryFile({content:e,path:o}),{...readMediaMetadata(e,i),path:r.resolvePath(o)}}async function resolveLink(e,t,n){let r=t.ctx.get(ChannelKey),i=r===void 0?`none`:getAdapterKind(r);if(r?.fetchFile!==void 0){let n;try{n=await r.fetchFile(e.href,t)}catch(e){throw e instanceof EveAttachmentError?new EveAttachmentError({adapterKind:i,cause:e.cause,kind:e.kind,message:e.message}):new EveAttachmentError({adapterKind:i,cause:e,kind:`resolver-threw`,message:`Attachment retrieval failed in the "${i}" channel.`})}if(n!==null)return Buffer.isBuffer(n)?{bytes:n}:n}return n(e,i)}function reconstitueFilePartUrls(e){let t=!1,n=e.map(e=>e.type===`file`&&isSerializedUrlFilePart(e.data)?(t=!0,{...e,data:deserializeUrlFilePart(e.data)}):e);return t?n:e}function sha256Prefix(e){return createHash(`sha256`).update(e).digest(`hex`).slice(0,16)}function safeFilename(e,t,n){let r=e===void 0?``:basename(e).replace(UNSAFE_FILENAME_CHARS,`_`),i=r.length>0?r:`file-${t}`,a=MEDIA_TYPE_EXTENSIONS[n];return a===void 0||extname(i)!==``?i:`${i}${a}`}export{ATTACHMENTS_ROOT,hydrateSandboxAttachments,moveToolResultFilesToUserMessages,stageAttachmentsForAdapter,stageAttachmentsToSandbox,stageToolResultMedia};
|
|
1
|
+
import{createHash}from"node:crypto";import{buildSessionHandle}from"#channel/session.js";import{createLogger}from"#internal/logging.js";import{getAdapterKind}from"#channel/adapter.js";import{contextStorage,loadContext}from"#context/container.js";import{SandboxKey}from"#context/keys.js";import{deserializeUrlFilePart,isSerializedUrlFilePart}from"#internal/attachments/url-refs.js";import{basename,dirname,extname}from"node:path";import{ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{createFrameworkUserMessage}from"#harness/messages.js";import{DEFAULT_UPLOAD_POLICY,isMediaTypeAllowed}from"#public/channels/upload-policy.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{readMediaMetadata,verifyMediaType}from"#internal/attachments/media-metadata.js";import{decodeSandboxRef,encodeSandboxRef,inlinesSandboxRefAsBytes,isSandboxRefUrl}from"#internal/attachments/sandbox-refs.js";import{isUnresolvedFileData,readFileData}from"#internal/attachments/data.js";import{EveAttachmentError}from"#internal/attachments/errors.js";import{maxBytesOf}from"#internal/attachments/limited-read.js";import{createPublicDownloads}from"#internal/attachments/public-link.js";const ATTACHMENTS_ROOT=`/workspace/.eve/attachments`,log=createLogger(`harness.attachment-staging`),UNSAFE_FILENAME_CHARS=/[^\w.-]+/g,MEDIA_TYPE_EXTENSIONS={"application/pdf":`.pdf`,"image/gif":`.gif`,"image/jpeg":`.jpg`,"image/png":`.png`,"image/webp":`.webp`};async function stageAttachmentsForAdapter(e,t,n){if(typeof e==`string`)return e;let r=reconstitueFilePartUrls(e),i=n.ctx.get(ChannelKey)?.uploadPolicy,a=createPublicDownloads(maxBytesOf(i??DEFAULT_UPLOAD_POLICY));return Promise.all(r.map(async e=>e.type===`file`?stageFilePart(e,t,n,a,i):e))}async function stageAttachmentsToSandbox(e){if(typeof e==`string`||!Array.isArray(e)||!hasFileParts(e))return e;let t=loadContext(),n=await activeSandbox(t.get(SandboxKey));if(n===null)return e.map(e=>e.type===`file`&&!isSandboxRefUrl(e.data)&&readFileData(e.data).kind!==`reference`?attachmentNote(e,`could not be stored: no sandbox is available.`):e);let r=t.get(ChannelKey);return stageAttachmentsForAdapter(e,n,r?buildAdapterContext(r,t):{ctx:t,state:{},session:buildSessionHandle(t)})}async function stageToolResultMedia(e){if(!e.some(hasInlineToolResultFile))return[...e];let t=await activeSandbox(contextStorage.getStore()?.get(SandboxKey));return Promise.all(e.map(async e=>{if(e.role!==`tool`||!hasInlineToolResultFile(e))return e;let n=await Promise.all(e.content.map(async e=>e.type===`tool-result`?{...e,output:await stageToolOutputFiles(e.output,t)}:e));return{...e,content:n}}))}async function hydrateSandboxAttachments(e){let t=replaceUnresolvedFileParts(e);if(!messagesContainSandboxRef(t))return t;let n=loadContext().get(SandboxKey);if(n===void 0)throw Error(`Cannot hydrate sandbox-ref FilePart: no SandboxKey is bound on the active eve context. Hydration must run inside a step scope with the framework sandbox provider installed.`);let r=await activeSandbox(n);return Promise.all(t.map(async e=>{if(!messageContainsSandboxRef(e))return e;let t=await hydrateMessageContent(e.content,r);return{...e,content:t}}))}async function activeSandbox(e){if(e===void 0)return null;try{return await e.get()}catch(e){return log.warn(`session sandbox unavailable, degrading attachments to text`,{error:e}),null}}function replaceUnresolvedFileParts(e){let t=!1,n=e.map(e=>{if(e.role!==`user`||!Array.isArray(e.content)||!e.content.some(isUnresolvedFilePart))return e;t=!0;let n=e.content.map(e=>isUnresolvedFilePart(e)?attachmentNote(e,`could not be retrieved.`):e);return{...e,content:n}});return t?n:e}function isUnresolvedFilePart(e){return e.type===`file`&&!isSandboxRefUrl(e.data)&&isUnresolvedFileData(e.data)}function hasFileParts(e){for(let t of e)if(t.type===`file`)return!0;return!1}function messagesContainSandboxRef(e){for(let t of e)if(messageContainsSandboxRef(t))return!0;return!1}function messageContainsSandboxRef(e){let t=e.content;if(!Array.isArray(t))return!1;for(let e of t)if(isSandboxRefFilePart(e)||e.type===`tool-result`&&contentOutputParts(e.output).some(isToolOutputRefFile))return!0;return!1}function contentOutputParts(e){return e.type===`content`?e.value:[]}function hasInlineToolResultFile(e){return e.role===`tool`&&e.content.some(e=>e.type===`tool-result`&&contentOutputParts(e.output).some(isInlineToolOutputFile))}function isInlineToolOutputFile(e){return e.type===`file`&&e.data.type===`data`}function isToolOutputRefFile(e){return e.type===`file`&&e.data.type===`url`&&isSandboxRefUrl(e.data.url)}async function stageToolOutputFiles(e,t){if(e.type!==`content`||!e.value.some(isInlineToolOutputFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isInlineToolOutputFile(e)||e.data.type!==`data`)return e;let n=readFileData(e.data.data);if(n.kind===`link`)return e;if(t===null||n.kind!==`bytes`)return{text:`Returned file ${e.filename??`file`} (${e.mediaType}) could not be stored.`,type:`text`};let r=await writeSandboxRef(n.bytes,e.mediaType,e.filename,t);return{...e,data:{type:`url`,url:encodeSandboxRef(r)},mediaType:r.mediaType}}));return{...e,value:n}}function isSandboxRefFilePart(e){return typeof e==`object`&&!!e&&e.type===`file`&&isSandboxRefUrl(e.data)}async function hydrateMessageContent(e,t){return Array.isArray(e)?(await Promise.all(e.map(async e=>{if(isSandboxRefFilePart(e)){let n=decodeSandboxRef(e.data),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await readSandboxRefBytes(n,t);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:i,mediaType:n.mediaType}]}if(e.type===`tool-result`){let n=e;return[{...n,output:await hydrateToolOutput(n.output,t)}]}return[e]}))).flat():e}async function hydrateToolOutput(e,t){if(e.type!==`content`||!e.value.some(isToolOutputRefFile))return e;let n=await Promise.all(e.value.map(async e=>{if(!isToolOutputRefFile(e)||e.data.type!==`url`)return[e];let n=decodeSandboxRef(e.data.url),r=renderSandboxRefAsTextPart(n);if(!inlinesSandboxRefAsBytes(n))return[r];let i=await readSandboxRefBytes(n,t);return i===null?[renderMissingSandboxRef(n)]:[r,{...e,data:{data:Buffer.from(i).toString(`base64`),type:`data`}}]}));return{...e,value:n.flat()}}async function readSandboxRefBytes(e,t){if(t===null)return null;let n=await t.readBinaryFile({path:e.path});return n===null?(log.warn(`sandbox-ref attachment bytes missing on hydration — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n.byteLength!==e.size||sha256Prefix(n)!==basename(dirname(e.path))?(log.warn(`sandbox-ref attachment bytes changed since staging — degrading to text reference`,{mediaType:e.mediaType,path:e.path,size:e.size}),null):n}function renderMissingSandboxRef(e){return{text:`FileNotFound: Current snapshot may be newer and does not contain ${e.path}.`,type:`text`}}function moveToolResultFilesToUserMessages(e){let t=[],n=[];for(let r of e){if(r.role!==`tool`&&n.length>0&&(t.push(createReturnedFilesMessage(n)),n=[]),r.role!==`tool`){t.push(r);continue}let e=r.content.map(e=>{if(e.type!==`tool-result`||e.output.type!==`content`)return e;let t=e.output.value.map(e=>{if(e.type!==`file`)return e;let t={data:e.data,mediaType:e.mediaType,type:`file`};return e.filename!==void 0&&(t.filename=e.filename),n.push(t),{text:`Attached file ${e.filename??`file`} (${e.mediaType}) follows this tool result.`,type:`text`}});return{...e,output:{...e.output,value:t}}});t.push({...r,content:e})}return n.length>0&&t.push(createReturnedFilesMessage(n)),t}function createReturnedFilesMessage(e){return createFrameworkUserMessage(`context.state`,[{text:`Files returned by the preceding tool results:`,type:`text`},...e])}function renderSandboxRefAsTextPart(e){return{text:`Attached file ${e.path} (${e.mediaType})`,type:`text`}}async function stageFilePart(e,t,n,r,i){if(isSandboxRefUrl(e.data))return e;let a=readFileData(e.data);if(a.kind===`bytes`)return stageResolvedBytes(e,{bytes:a.bytes},t,i);if(a.kind===`reference`)return e;if(a.kind===`unreadable`)return log.warn(`attachment data is not bytes, base64, or a URL — degrading to text part`,{filename:e.filename,mediaType:e.mediaType}),attachmentNote(e,`could not be read.`);let o;try{o=await resolveLink(a.url,n,r)}catch(t){if(!(t instanceof EveAttachmentError))throw t;return log.warn(`attachment resolver failed — degrading to text part`,{adapterKind:t.adapterKind,error:t.cause,filename:e.filename,kind:t.kind}),attachmentNote(e,`could not be retrieved: ${t.message}`)}return stageResolvedBytes(e,o,t,i)}function attachmentNote(e,t){return{text:`Attachment ${e.filename?.trim()||`file`} ${t}`,type:`text`}}async function stageResolvedBytes(e,t,n,r){let i=verifyMediaType(t.bytes,t.mediaType??e.mediaType??`application/octet-stream`);if(r!==void 0){let n=maxBytesOf(r);if(t.bytes.byteLength>n)return attachmentNote(e,`was not accepted: it is ${t.bytes.byteLength} bytes, over this channel's ${n}-byte upload limit.`);if(!isMediaTypeAllowed(i,r))return attachmentNote(e,`was not accepted: this channel doesn't accept ${i} files.`)}let a=await writeSandboxRef(t.bytes,i,t.filename??e.filename,n);return{...e,data:encodeSandboxRef(a),filename:a.path,mediaType:a.mediaType}}async function writeSandboxRef(e,t,n,r){let i=verifyMediaType(e,t),a=sha256Prefix(e),o=`${ATTACHMENTS_ROOT}/${a}/${safeFilename(n,a,i)}`;return await r.writeBinaryFile({content:e,path:o}),{...readMediaMetadata(e,i),path:r.resolvePath(o)}}async function resolveLink(e,t,n){let r=t.ctx.get(ChannelKey),i=r===void 0?`none`:getAdapterKind(r);if(r?.fetchFile!==void 0){let n;try{n=await r.fetchFile(e.href,t)}catch(e){throw e instanceof EveAttachmentError?new EveAttachmentError({adapterKind:i,cause:e.cause,kind:e.kind,message:e.message}):new EveAttachmentError({adapterKind:i,cause:e,kind:`resolver-threw`,message:`Attachment retrieval failed in the "${i}" channel.`})}if(n!==null)return Buffer.isBuffer(n)?{bytes:n}:n}return n(e,i)}function reconstitueFilePartUrls(e){let t=!1,n=e.map(e=>e.type===`file`&&isSerializedUrlFilePart(e.data)?(t=!0,{...e,data:deserializeUrlFilePart(e.data)}):e);return t?n:e}function sha256Prefix(e){return createHash(`sha256`).update(e).digest(`hex`).slice(0,16)}function safeFilename(e,t,n){let r=e===void 0?``:basename(e).replace(UNSAFE_FILENAME_CHARS,`_`),i=r.length>0?r:`file-${t}`,a=MEDIA_TYPE_EXTENSIONS[n];return a===void 0||extname(i)!==``?i:`${i}${a}`}export{ATTACHMENTS_ROOT,hydrateSandboxAttachments,moveToolResultFilesToUserMessages,stageAttachmentsForAdapter,stageAttachmentsToSandbox,stageToolResultMedia};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{createFrameworkUserMessage,isFrameworkUserMessage}from"#harness/messages.js";import{COMPACTION_CHECKPOINT_MARKER,COMPACTION_PROMPT_ENVELOPE,COMPACTION_RESUMPTION_MESSAGE,TRANSCRIPT_PAYLOAD_LIMIT,createCompactionPrompt,sliceUtf16Safe,stubContentOutputFileParts}from"#harness/compaction/prompt.js";import{estimateTokens}from"#harness/token-estimate.js";const COMPACTION_PROMPT_OVERHEAD_TOKENS=estimateTokens([{content:COMPACTION_PROMPT_ENVELOPE.system,role:`system`},createFrameworkUserMessage(`context.compaction`,COMPACTION_PROMPT_ENVELOPE.prompt)]);function getInputTokenCount(e,t,n=0,r=0){let i=t.lastKnownInputTokens,a=t.lastKnownPromptMessageCount;return i===void 0||a===void 0||!Number.isInteger(a)||a<0||a>e.length?estimateTokens(e)+n:i+estimateTokens(e.slice(a))+Math.max(0,n-r)}function shouldCompact(e,t,n=0,r=0){return e.length>0&&getInputTokenCount(e,t,n,r)+COMPACTION_PROMPT_OVERHEAD_TOKENS>t.threshold}const COMPACTION_HEURISTICS=[toolResultCapHeuristic];function toolResultCapHeuristic(e){let t=withResumptionGuard([...e.previousCheckpoint===void 0?[]:[createFrameworkUserMessage(`context.compaction`,COMPACTION_CHECKPOINT_MARKER),{content:e.previousCheckpoint,role:`assistant`}],...capToolResults(e.older),...e.recent],e.conversation,e.config.threshold);return evaluateThreshold(t,e.config,`should-compact`,e.tokenEstimateAdjustment).type===`within-limit`?{messages:t,type:`within-limit`}:{type:`insufficient`}}function evaluateThreshold(e,t,n,r=0){let i=n===`should-compact`?COMPACTION_PROMPT_OVERHEAD_TOKENS:0,a=estimateTokens(e)+i+r;return{estimatedTokens:a,type:a<=t.threshold?`within-limit`:`over-limit`}}async function compactMessages(e,t,n,r=!1,i){let{conversation:a,previousCheckpoint:o}=extractPreviousCheckpoint(e),s=selectRecentWindowSize(a,r?{...t,recentWindowSize:1}:t);if(!r){let{older:n,recent:r}=splitMessagesForCompaction(a,s);if(n.length===0&&o===void 0)return keepNonToolResultMessages(r);let c=Math.max(0,(i??getInputTokenCount(e,t))-estimateTokens(e));for(let e of COMPACTION_HEURISTICS){let i=e({config:t,conversation:a,older:n,previousCheckpoint:o,recent:r,tokenEstimateAdjustment:c});if(i.type===`within-limit`)return i.messages}}for(;;){let{older:e,recent:r}=splitMessagesForCompaction(a,s),i=createCompactionPrompt({messages:e,previousCheckpoint:o,transcriptBudgetTokens:t.threshold}),c=await n({messages:[createFrameworkUserMessage(`context.compaction`,i.prompt)],system:i.system}),l=[createFrameworkUserMessage(`context.compaction`,COMPACTION_CHECKPOINT_MARKER),{content:c,role:`assistant`}],u=withResumptionGuard([...l,...r],a,t.threshold);if(evaluateThreshold(u,t,`estimate`).type===`within-limit`)return u;let d=withResumptionGuard([...l,...keepNonToolResultMessages(r)],a,t.threshold);if(evaluateThreshold(d,t,`estimate`).type===`within-limit`||s===0)return d;--s}}function capToolResults(e){return e.map(e=>{if(e.role!==`tool`||typeof e.content==`string`)return e;let t=!1,n=e.content.map(e=>{if(e.type!==`tool-result`)return e;let n=stubContentOutputFileParts(e.output),r=
|
|
1
|
+
import{createFrameworkUserMessage,isFrameworkUserMessage}from"#harness/messages.js";import{COMPACTION_CHECKPOINT_MARKER,COMPACTION_PROMPT_ENVELOPE,COMPACTION_RESUMPTION_MESSAGE,TRANSCRIPT_PAYLOAD_LIMIT,createCompactionPrompt,serializeToolResultOutput,sliceUtf16Safe,stubContentOutputFileParts}from"#harness/compaction/prompt.js";import{estimateTokens}from"#harness/token-estimate.js";const COMPACTION_PROMPT_OVERHEAD_TOKENS=estimateTokens([{content:COMPACTION_PROMPT_ENVELOPE.system,role:`system`},createFrameworkUserMessage(`context.compaction`,COMPACTION_PROMPT_ENVELOPE.prompt)]);function getInputTokenCount(e,t,n=0,r=0){let i=t.lastKnownInputTokens,a=t.lastKnownPromptMessageCount;return i===void 0||a===void 0||!Number.isInteger(a)||a<0||a>e.length?estimateTokens(e)+n:i+estimateTokens(e.slice(a))+Math.max(0,n-r)}function shouldCompact(e,t,n=0,r=0){return e.length>0&&getInputTokenCount(e,t,n,r)+COMPACTION_PROMPT_OVERHEAD_TOKENS>t.threshold}const COMPACTION_HEURISTICS=[toolResultCapHeuristic];function toolResultCapHeuristic(e){let t=withResumptionGuard([...e.previousCheckpoint===void 0?[]:[createFrameworkUserMessage(`context.compaction`,COMPACTION_CHECKPOINT_MARKER),{content:e.previousCheckpoint,role:`assistant`}],...capToolResults(e.older),...e.recent],e.conversation,e.config.threshold);return evaluateThreshold(t,e.config,`should-compact`,e.tokenEstimateAdjustment).type===`within-limit`?{messages:t,type:`within-limit`}:{type:`insufficient`}}function evaluateThreshold(e,t,n,r=0){let i=n===`should-compact`?COMPACTION_PROMPT_OVERHEAD_TOKENS:0,a=estimateTokens(e)+i+r;return{estimatedTokens:a,type:a<=t.threshold?`within-limit`:`over-limit`}}async function compactMessages(e,t,n,r=!1,i){let{conversation:a,previousCheckpoint:o}=extractPreviousCheckpoint(e),s=selectRecentWindowSize(a,r?{...t,recentWindowSize:1}:t);if(!r){let{older:n,recent:r}=splitMessagesForCompaction(a,s);if(n.length===0&&o===void 0)return keepNonToolResultMessages(r);let c=Math.max(0,(i??getInputTokenCount(e,t))-estimateTokens(e));for(let e of COMPACTION_HEURISTICS){let i=e({config:t,conversation:a,older:n,previousCheckpoint:o,recent:r,tokenEstimateAdjustment:c});if(i.type===`within-limit`)return i.messages}}for(;;){let{older:e,recent:r}=splitMessagesForCompaction(a,s),i=createCompactionPrompt({messages:e,previousCheckpoint:o,transcriptBudgetTokens:t.threshold}),c=await n({messages:[createFrameworkUserMessage(`context.compaction`,i.prompt)],system:i.system}),l=[createFrameworkUserMessage(`context.compaction`,COMPACTION_CHECKPOINT_MARKER),{content:c,role:`assistant`}],u=withResumptionGuard([...l,...r],a,t.threshold);if(evaluateThreshold(u,t,`estimate`).type===`within-limit`)return u;let d=withResumptionGuard([...l,...keepNonToolResultMessages(r)],a,t.threshold);if(evaluateThreshold(d,t,`estimate`).type===`within-limit`||s===0)return d;--s}}function capToolResults(e){return e.map(e=>{if(e.role!==`tool`||typeof e.content==`string`)return e;let t=!1,n=e.content.map(e=>{if(e.type!==`tool-result`)return e;let n=stubContentOutputFileParts(e.output),r=serializeToolResultOutput(n);return r.length<=TRANSCRIPT_PAYLOAD_LIMIT?n===e.output?e:(t=!0,{...e,output:n}):(t=!0,{...e,output:{type:`text`,value:`[Truncated by eve: tool result reduced during context compaction. Re-run the tool if you need the full output.]
|
|
2
|
+
|
|
3
|
+
${sliceUtf16Safe(r,TRANSCRIPT_PAYLOAD_LIMIT-113)}`}})});return t?{...e,content:n}:e})}function withResumptionGuard(e,t,n){let r=e.at(-1)?.role,i=findLastRealUserMessage(t),a=i!==void 0&&e.some(e=>e.role===`user`&&e.content===i.content);return r!==void 0&&r!==`assistant`?r===`tool`&&i!==void 0&&!a&&estimateTokens([i])<=n?[...e,i]:e:[...e,i!==void 0&&!a?i:createFrameworkUserMessage(`execution.continuation`,COMPACTION_RESUMPTION_MESSAGE)]}function findLastRealUserMessage(e){for(let t=e.length-1;t>=0;--t){let n=e[t];if(n?.role===`user`&&typeof n.content==`string`&&!isFrameworkUserMessage(n))return n}}function extractPreviousCheckpoint(e){let t=e[0],n=e[1];return t?.role!==`user`||t.content!==COMPACTION_CHECKPOINT_MARKER||n?.role!==`assistant`?{conversation:[...e],previousCheckpoint:void 0}:{conversation:e.slice(2),previousCheckpoint:assistantMessageText(n)}}function keepNonToolResultMessages(e){let t=[];for(let n of e)if(n.role!==`tool`){if(n.role===`assistant`){let e=assistantMessageText(n);e.length>0&&t.push({content:e,role:`assistant`});continue}t.push(n)}return t}function assistantMessageText(e){return typeof e.content==`string`?e.content.trim():e.content.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim()}function selectRecentWindowSize(e,t){let n=Math.min(t.recentWindowSize,Math.max(e.length-1,0)),r=resolveCompactionSummaryReserve(t),i=0,a=0;for(let o=e.length-1;o>=0&&i<n;--o){let n=e[o];if(n===void 0)continue;let s=estimateTokens([n]);if(a+s+r>t.threshold)break;a+=s,i+=1}return i}function resolveCompactionSummaryReserve(e){return Math.min(2048,Math.max(64,Math.floor(e.threshold/4)))}function splitMessagesForCompaction(e,t){if(t<=0)return{older:[...e],recent:[]};let n=e.length-t;for(;n<e.length&&e[n]?.role===`tool`;)n+=1;return{older:e.slice(0,n),recent:e.slice(n)}}export{compactMessages,getInputTokenCount,shouldCompact};
|
|
@@ -26,6 +26,13 @@ export declare function createCompactionPrompt(input: {
|
|
|
26
26
|
readonly transcriptBudgetTokens?: number;
|
|
27
27
|
}): CompactionPrompt;
|
|
28
28
|
export declare const TRANSCRIPT_PAYLOAD_LIMIT = 2000;
|
|
29
|
+
/**
|
|
30
|
+
* The text a tool-result output is measured and clipped by, in history
|
|
31
|
+
* capping and in the summarizer transcript alike: a text output is its
|
|
32
|
+
* value, any other output its JSON. Sharing it keeps a capped history
|
|
33
|
+
* result whole when the summarizer renders it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function serializeToolResultOutput(output: unknown): string;
|
|
29
36
|
/**
|
|
30
37
|
* Replaces the file parts of a `content` tool output with their text stubs,
|
|
31
38
|
* leaving every other output shape untouched. History capping uses this so a
|
|
@@ -23,4 +23,4 @@ Make completed work explicit so the next model does not repeat it. Keep complete
|
|
|
23
23
|
Large tool outputs are the main thing to compress: reduce each to the findings the next model needs — what was searched or read, what it established, and the exact identifiers involved — rather than reproducing the output. The next model cannot see the originals, so nothing it would need to act on may be lost.`}function formatCompactionTranscript(e){let t=e.filter(e=>e.content.trim().length>0).map(e=>`### ${e.role}\n${e.content.trim()}`);return t.length===0?`(empty)`:t.join(`
|
|
24
24
|
|
|
25
25
|
`)}function renderCompactionMessageContent(e,t){return typeof e.content==`string`?renderConversationText(e.content,t):e.content.map(e=>renderCompactionContentPart(e,t)).filter(e=>e.length>0).join(`
|
|
26
|
-
`).trim()}function renderCompactionContentPart(e,t){switch(e.type){case`text`:return renderConversationText(e.text,t);case`reasoning`:return``;case`file`:return renderAttachedFileStub(e.filename,e.mediaType);case`tool-call`:return renderTranscriptToolCall(e,t);case`tool-result`:return renderTranscriptToolResult(e,t);default:return``}}const TRANSCRIPT_PAYLOAD_LIMIT=2e3;function renderTranscriptToolCall(e,t){return renderToolCall(e,t===void 0?TRANSCRIPT_PAYLOAD_LIMIT:280)}function renderTranscriptToolResult(e,t){let n=t===void 0?TRANSCRIPT_PAYLOAD_LIMIT:280,r=e.isError?`errored`:`returned`,i=renderToolResultOutput(e.output,n);return i?`Tool ${e.toolName} ${r} ${i}`:`Tool ${e.toolName} ${r}`}function renderToolResultOutput(e,t){let n=contentToolOutputParts(e);return n===void 0?
|
|
26
|
+
`).trim()}function renderCompactionContentPart(e,t){switch(e.type){case`text`:return renderConversationText(e.text,t);case`reasoning`:return``;case`file`:return renderAttachedFileStub(e.filename,e.mediaType);case`tool-call`:return renderTranscriptToolCall(e,t);case`tool-result`:return renderTranscriptToolResult(e,t);default:return``}}const TRANSCRIPT_PAYLOAD_LIMIT=2e3;function renderTranscriptToolCall(e,t){return renderToolCall(e,t===void 0?TRANSCRIPT_PAYLOAD_LIMIT:280)}function renderTranscriptToolResult(e,t){let n=t===void 0?TRANSCRIPT_PAYLOAD_LIMIT:280,r=e.isError?`errored`:`returned`,i=renderToolResultOutput(e.output,n);return i?`Tool ${e.toolName} ${r} ${i}`:`Tool ${e.toolName} ${r}`}function renderToolResultOutput(e,t){let n=contentToolOutputParts(e);return capText(n===void 0?serializeToolResultOutput(e):n.map(e=>renderContentToolOutputPart(e,t)).filter(e=>e.length>0).join(` `),t)}function serializeToolResultOutput(e){if(typeof e==`object`&&e){let t=e;if(t.type===`text`&&typeof t.value==`string`)return t.value}return JSON.stringify(e)??``}function contentToolOutputParts(e){if(typeof e!=`object`||!e)return;let t=e;return t.type===`content`&&Array.isArray(t.value)?t.value:void 0}function stubContentOutputFileParts(e){let t=contentToolOutputParts(e);if(t===void 0)return e;let n=!1,r=t.map(e=>{if(typeof e!=`object`||!e)return e;let t=e;return t.type!==`file`&&t.type!==`media`?e:(n=!0,{text:renderAttachedFileStub(contentFileName(e),typeof t.mediaType==`string`?t.mediaType:`unknown`),type:`text`})});return n?{type:`content`,value:r}:e}function renderContentToolOutputPart(e,t){if(typeof e!=`object`||!e)return renderPayload(e,t);let n=e;return n.type===`text`&&typeof n.text==`string`?n.text:n.type===`file`||n.type===`media`?renderAttachedFileStub(contentFileName(e),typeof n.mediaType==`string`?n.mediaType:`unknown`):renderPayload(e,t)}function contentFileName(e){let{data:t,filename:n}=e,r=t;return r?.type===`url`&&isSandboxRefUrl(r.url)?decodeSandboxRef(r.url).path:typeof n==`string`?n:void 0}function renderToolCall(e,t){let n=renderPayload(e.input,t);return n?`Called ${e.toolName} with ${n}`:`Called ${e.toolName}`}function renderPayload(e,t){return e===void 0?``:capText(JSON.stringify(e)??``,t)}function renderAttachedFileStub(e,t){return`Attached file ${e??`attachment`} (${t})`}function renderConversationText(e,t){return t===void 0?e.trim():capText(e,t)}function sliceUtf16Safe(e,t){if(t<=0)return``;if(e.length<=t)return e;let n=t,r=e.charCodeAt(n-1);return r>=55296&&r<=56319&&--n,e.slice(0,n)}function capText(e,t){let n=e.replace(/\s+/g,` `).trim();return n.length<=t?n:`${sliceUtf16Safe(n,t).trimEnd()}…`}export{COMPACTION_CHECKPOINT_MARKER,COMPACTION_PROMPT_ENVELOPE,COMPACTION_RESUMPTION_MESSAGE,TRANSCRIPT_PAYLOAD_LIMIT,createCompactionPrompt,serializeToolResultOutput,sliceUtf16Safe,stubContentOutputFileParts};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{supersededChallenges,withSignIns}from"./sign-ins.js";import{canonicalize,compactInput,isEmptyInput,resolveTextInput,withoutResponses}from"./delivery.js";import{openInputs,turnCoordinates}from"#protocol/session-projection.js";import{readClientContext}from"#internal/client-context.js";import{createActionResultEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageCompletedEvent}from"#protocol/message.js";import{coalesceTurnInputs,createFrameworkUserMessage}from"#harness/messages.js";import{turnPosition}from"#harness/session-machine/view.js";import{renderPendingApprovalsSnippet}from"#harness/hitl/approval-prompt.js";import{hold,ownOpenRequestIds,settle,stepCallIds,suspend,withResult,withoutApproved}from"#harness/session-machine/transitions.js";import{withoutCalls}from"#harness/inline-tool-authorization.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{authorizationEventFields}from"#harness/authorization-event-fields.js";import{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,resolveApprovalOutcome,resolveInputOutcome,unavailableToolMessage}from"#harness/input-request-resolution.js";import{resolveSessionLimitContinuation}from"#harness/hitl/budget-request.js";import{signInWithdrawn}from"#harness/session-machine/events.js";function parkOnApprovals(e,t){let n=t.requester?.principalType===`anonymous`?null:t.requester,r=t.messages.findIndex(e=>e.role!==`tool`),i=r===-1?t.messages:t.messages.slice(0,r),a=renderPendingApprovalsSnippet(t.requests),o=suspend(e.turn,{event:t.event,messages:t.messages.slice(i.length),requester:n,requests:t.requests,responseAuthRequiredRequestIds:t.responseAuthRequiredRequestIds,tasks:t.tasks});return{commit:[...i,...a===void 0?[]:[createFrameworkUserMessage(`context.state`,a)]],events:t.tasks.length>0?[]:[createInputRequestedEvent({requests:t.requests,...t.event})],turn:o}}function dispatch(e,t){let n=e.turn.suspended.map(e=>{let n=stepCallIds(e),r=t.tasks.filter(e=>n.has(e.callId));return r.length===0?e:{...withoutApproved(e,new Set(r.map(e=>e.callId))),tasks:[...e.tasks,...r]}});return{events:[],turn:{...e.turn,suspended:n}}}function deferInput(e,t){return{events:[],turn:withQueued(e.turn,t)}}function withQueued(e,t){return t===void 0||isEmptyInput(t)?e:{...e,queued:e.queued===void 0?t:coalesceTurnInputs(e.queued,t)}}function answer(e,t){let{policy:n}=t,{projection:r}=e,i=turnPosition(r),a=[...n.feedback.map(e=>createMessageCompletedEvent({message:e,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId})),...reportApprovalProgress(r,n.audit,n.challengesAtStart)],o=t.takeQueued?{...e.turn,queued:void 0}:e.turn,done=e=>({events:a,resolved:[],turn:o,...e}),queue=e=>{o=withQueued(o,e)};if(n.kind===`park`)return done({next:`park`});if(n.kind===`continue-coordination`)return queue(n.stepInput),done({next:`repeat`});if(n.challenges.length>0)return done({next:`sign-in`});let s=t.delivery,c=openInputs(r).find(t=>t.request.kind===`session-limit`&&ownOpenRequestIds(e).has(t.request.requestId)),l=o.suspended.filter(e=>e.requests.length>0);if(c===void 0&&l.length===0)return done({input:s,next:`continue`});let u=c===void 0?s:resolveTextInput({requests:[c.request]},s),d=canonicalize(u?.inputResponses??[]),f=new Map(d.map(e=>[e.requestId,e])),p=l.filter(e=>e.requests.every(e=>f.has(e.requestId))),leftoverFor=e=>d.filter(t=>e.some(e=>e.requests.some(e=>e.requestId===t.requestId))),park=()=>(queue(compactInput(u)),done({next:`park`}));if(d.length===0&&u?.message===void 0)return park();if(c!==void 0){let e=f.get(c.request.requestId);if(e===void 0)return park();let t={event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},inputs:[{outcome:resolveInputOutcome(c.request.kind,e),request:c.request,response:e}]};a.push(resolvedEvent(t));let n=leftoverFor(l);return n.length>0&&queue({inputResponses:n}),done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),limit:resolveSessionLimitContinuation({requests:[c.request],responses:d}),next:`continue`,resolved:[t]})}if(p.length===0&&u?.message===void 0)return park();p.length===0&&p.push(l[0]);let m=leftoverFor(l.filter(e=>!p.includes(e)));m.length>0&&queue({inputResponses:m});let h=new Set(o.grants),g=[],_=[],v=new Set(n.audit.settlements.filter(e=>e.outcome===`unavailable`).map(e=>e.requestId)),y=o.suspended.map(e=>{if(!p.includes(e))return e;let n=e.messages,r=[];for(let i of e.requests){let{callId:a,toolName:o}=i.action;if(v.has(i.requestId)){let r=failedCall({callId:a,
|
|
1
|
+
import{supersededChallenges,withSignIns}from"./sign-ins.js";import{canonicalize,compactInput,isEmptyInput,resolveTextInput,withoutResponses}from"./delivery.js";import{openInputs,turnCoordinates}from"#protocol/session-projection.js";import{readClientContext}from"#internal/client-context.js";import{createActionResultEvent,createApprovalCandidateEvent,createApprovalSettledEvent,createAuthorizationCompletedEvent,createAuthorizationRequiredEvent,createInputRequestedEvent,createInputResolvedEvent,createMessageCompletedEvent}from"#protocol/message.js";import{coalesceTurnInputs,createFrameworkUserMessage}from"#harness/messages.js";import{turnPosition}from"#harness/session-machine/view.js";import{renderPendingApprovalsSnippet}from"#harness/hitl/approval-prompt.js";import{hold,ownOpenRequestIds,settle,stepCallIds,suspend,withResult,withoutApproved}from"#harness/session-machine/transitions.js";import{withoutCalls}from"#harness/inline-tool-authorization.js";import{isApprovalRequest}from"#harness/input-request-class.js";import{authorizationEventFields}from"#harness/authorization-event-fields.js";import{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,resolveApprovalOutcome,resolveInputOutcome,unavailableToolMessage}from"#harness/input-request-resolution.js";import{resolveSessionLimitContinuation}from"#harness/hitl/budget-request.js";import{signInWithdrawn}from"#harness/session-machine/events.js";function parkOnApprovals(e,t){let n=t.requester?.principalType===`anonymous`?null:t.requester,r=t.messages.findIndex(e=>e.role!==`tool`),i=r===-1?t.messages:t.messages.slice(0,r),a=renderPendingApprovalsSnippet(t.requests),o=suspend(e.turn,{event:t.event,messages:t.messages.slice(i.length),requester:n,requests:t.requests,responseAuthRequiredRequestIds:t.responseAuthRequiredRequestIds,tasks:t.tasks});return{commit:[...i,...a===void 0?[]:[createFrameworkUserMessage(`context.state`,a)]],events:t.tasks.length>0?[]:[createInputRequestedEvent({requests:t.requests,...t.event})],turn:o}}function dispatch(e,t){let n=e.turn.suspended.map(e=>{let n=stepCallIds(e),r=t.tasks.filter(e=>n.has(e.callId));return r.length===0?e:{...withoutApproved(e,new Set(r.map(e=>e.callId))),tasks:[...e.tasks,...r]}});return{events:[],turn:{...e.turn,suspended:n}}}function deferInput(e,t){return{events:[],turn:withQueued(e.turn,t)}}function withQueued(e,t){return t===void 0||isEmptyInput(t)?e:{...e,queued:e.queued===void 0?t:coalesceTurnInputs(e.queued,t)}}function answer(e,t){let{policy:n}=t,{projection:r}=e,i=turnPosition(r),a=[...n.feedback.map(e=>createMessageCompletedEvent({message:e,sequence:i.sequence,stepIndex:i.stepIndex,turnId:i.turnId})),...reportApprovalProgress(r,n.audit,n.challengesAtStart)],o=t.takeQueued?{...e.turn,queued:void 0}:e.turn,done=e=>({events:a,resolved:[],turn:o,...e}),queue=e=>{o=withQueued(o,e)};if(n.kind===`park`)return done({next:`park`});if(n.kind===`continue-coordination`)return queue(n.stepInput),done({next:`repeat`});if(n.challenges.length>0)return done({next:`sign-in`});let s=t.delivery,c=openInputs(r).find(t=>t.request.kind===`session-limit`&&ownOpenRequestIds(e).has(t.request.requestId)),l=o.suspended.filter(e=>e.requests.length>0);if(c===void 0&&l.length===0)return done({input:s,next:`continue`});let u=c===void 0?s:resolveTextInput({requests:[c.request]},s),d=canonicalize(u?.inputResponses??[]),f=new Map(d.map(e=>[e.requestId,e])),p=l.filter(e=>e.requests.every(e=>f.has(e.requestId))),leftoverFor=e=>d.filter(t=>e.some(e=>e.requests.some(e=>e.requestId===t.requestId))),park=()=>(queue(compactInput(u)),done({next:`park`}));if(d.length===0&&u?.message===void 0)return park();if(c!==void 0){let e=f.get(c.request.requestId);if(e===void 0)return park();let t={event:{sequence:c.sequence,stepIndex:c.stepIndex,turnId:c.turnId},inputs:[{outcome:resolveInputOutcome(c.request.kind,e),request:c.request,response:e}]};a.push(resolvedEvent(t));let n=leftoverFor(l);return n.length>0&&queue({inputResponses:n}),done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),limit:resolveSessionLimitContinuation({requests:[c.request],responses:d}),next:`continue`,resolved:[t]})}if(p.length===0&&u?.message===void 0)return park();p.length===0&&p.push(l[0]);let m=leftoverFor(l.filter(e=>!p.includes(e)));m.length>0&&queue({inputResponses:m});let h=new Set(o.grants),g=[],_=[],v=new Set(n.audit.settlements.filter(e=>e.outcome===`unavailable`).map(e=>e.requestId)),y=o.suspended.map(e=>{if(!p.includes(e))return e;let n=e.messages,r=[];for(let i of e.requests){let{callId:a,toolName:o}=i.action;if(v.has(i.requestId)){let r=failedCall({callId:a,failure:unavailableToolMessage(o,t.searchable(i)),toolName:o});n=withResult(n,r.part),_.push(createActionResultEvent({result:r.result,...e.event}));continue}let{approved:s,reason:c,status:l}=resolveApprovalOutcome(f.get(i.requestId));if(s){h.add(t.approvalKey(i)??o),r.push(i);continue}n=withResult(n,{output:{reason:c,type:`execution-denied`},toolCallId:a,toolName:o,type:`tool-result`}),_.push(createActionResultEvent({rejected:!0,result:{callId:a,isError:!0,kind:`tool-result`,output:{approval:{requestId:i.requestId,status:l},code:`TOOL_EXECUTION_DENIED`,message:c??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}},toolName:o},...e.event}))}g.push({event:e.event,inputs:e.requests.map(e=>{let t=f.get(e.requestId);return{outcome:resolveInputOutcome(e.kind,t),request:e,response:t}})});let i=[...e.approved??[],...r];return{...e,messages:n,requests:[],...i.length>0&&{approved:i}}});return a.push(...g.map(resolvedEvent),..._),o={...o,grants:[...h],suspended:y},done({consumedMessage:u?.messageConsumed,input:withoutResponses(u),next:`continue`,resolved:g})}function resolvedEvent(e){return createInputResolvedEvent({resolutions:e.inputs.map(e=>{let t={kind:e.request.kind,outcome:e.outcome,requestId:e.request.requestId};return e.response===void 0?t:{...t,response:e.response}}),...e.event})}function reportApprovalProgress(e,t,n){let r=turnCoordinates(e),isOpen=t=>{let n=e.inputs[t];return n!==void 0&&n.status!==`settled`},i=[];for(let a of n){let n=t.candidateHistory.some(e=>e.candidateId===a.candidateId&&e.status===`timed-out`),o=e.authorizations[a.attemptId??a.name];n&&o?.status===`required`&&i.push(createAuthorizationCompletedEvent({...authorizationEventFields(a),outcome:`failed`,reason:`The approval response expired. Please submit a new response.`,...r}))}for(let n of t.activeCandidates)e.candidates[n.candidateId]===void 0&&isOpen(n.requestId)&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:`pending`,requestId:n.requestId,responderPrincipalId:n.responder.principalId,...r}));for(let n of t.candidateHistory)n.status!==`allowed`&&n.status!==`authorization-required`&&e.inputs[n.requestId]!==void 0&&e.candidates[n.candidateId]?.outcome!==n.status&&i.push(createApprovalCandidateEvent({candidateId:n.candidateId,outcome:n.status,requestId:n.requestId,responderPrincipalId:n.responder.principalId,reason:n.reason,...r}));for(let e of t.settlements)isOpen(e.requestId)&&e.outcome!==`unavailable`&&i.push(createApprovalSettledEvent({outcome:e.outcome===`allowed`?`approved`:`cancelled`,requestId:e.requestId,responderPrincipalId:e.actor.principalId,...r}));return i}function hasRunnableQueue(e){let t=e.turn.queued;if(t===void 0)return!1;let n=[...t.inputResponses??[],...(t.attributedInputResponses??[]).map(({response:e})=>e)],r=new Set(n.map(e=>e.requestId)),i=openInputs(e.projection).find(e=>e.request.kind===`session-limit`);return i===void 0?t.message!==void 0||(t.context?.length??0)>0||readClientContext(t)!==void 0||t.outputSchema!==void 0||(t.runtimeActionResults?.length??0)>0||n.length!==0&&e.turn.suspended.some(e=>e.requests.length>0&&e.requests.every(e=>r.has(e.requestId))):r.has(i.request.requestId)}function grantedApprovalKeys(e,t){let n=new Set(e.turn.grants);for(let r of e.turn.suspended)for(let e of r.requests)isApprovalRequest(e)&&n.delete(t(e)??e.action.toolName);return n}function approvingSteps(e,t){let n=e.turn.suspended.filter(e=>e.requests.length>0),r=new Map((t?.inputResponses??[]).map(e=>[e.requestId,e.optionId]));return n.filter(e=>e.requests.every(e=>r.has(e.requestId))&&e.requests.some(e=>isApprovalRequest(e)&&r.get(e.requestId)===`approve`))}function stepForRequest(e,t){return e.turn.suspended.find(e=>e.requests.some(e=>e.requestId===t))}function withdrawSignIns(e,t){return{events:e.signIns.flatMap(n=>{let r=e.projection.authorizations[n.attemptId??n.name];return r?.status===`required`?[signInWithdrawn(r,t)]:[]}),signIns:[],turn:e.turn}}function requestLimit(e,t){let n=turnPosition(e.projection);return{events:[createInputRequestedEvent({requests:[t.request],sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId}),...hold(e,{on:`input`}).events],turn:e.turn}}function requireSignIn(e,t){let n=turnPosition(e.projection),r={sequence:n.sequence,stepIndex:n.stepIndex,turnId:n.turnId},i=[...supersededChallenges(e.signIns,t.challenges).map(e=>createAuthorizationCompletedEvent({...authorizationEventFields(e),outcome:`failed`,reason:`Superseded by a newer authorization attempt.`,...r})),...t.challenges.map(e=>createAuthorizationRequiredEvent({...authorizationEventFields(e),description:e.challenge.instructions??`Authorization required for ${e.name}`,webhookUrl:e.hookUrl,...r}))];i.push(...hold(e,{on:`input`}).events);let a=t.queued===void 0?e.turn.queued:e.turn.queued===void 0?t.queued:coalesceTurnInputs(e.turn.queued,t.queued),o=withSignIns(e.signIns,t.challenges),s=new Set([...t.callIdsByName?.values()??[]].flat()),c=e.turn.suspended.map(e=>[...stepCallIds(e)].some(e=>s.has(e))?{...e,messages:withoutCalls(e.messages,s)}:e);if(c.every((t,n)=>t===e.turn.suspended[n]))return{events:i,signIns:o,turn:{...e.turn,queued:a}};let l=settle({...e,turn:{...e.turn,queued:a,suspended:c}},{results:[]});return{commit:l.commit,events:i,signIns:o,turn:l.turn}}export{answer,approvingSteps,deferInput,dispatch,grantedApprovalKeys,hasRunnableQueue,parkOnApprovals,requestLimit,requireSignIn,stepForRequest,withdrawSignIns};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{asSchema}from"ai";import{createLogger,logError}from"#internal/logging.js";import{toError}from"#shared/errors.js";import{createActionPartialEvent,createActionResultEvent}from"#protocol/message.js";import{SEARCH_TOOL_NAME}from"#protocol/catalog-tools.js";import{toModelSchema}from"#tools/schema.js";import{parseJsonObject}from"#shared/json.js";import{toolCallModelOutput}from"#harness/tool-call-io.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{createRuntimeToolResultFromValue}from"#harness/action-result-helpers.js";import{projectDeltaPresentation,projectResultPresentation}from"#harness/tool-presentation.js";import{isInlineAuthorizationToolResult}from"#harness/inline-tool-authorization.js";import{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,unavailableToolMessage}from"#harness/input-request-resolution.js";import{recheckApprovedCall,wrapToolExecute}from"#harness/tools.js";const log=createLogger(`harness.tool-loop`),APPROVED_CALL_INTERRUPTED_MESSAGE=`The turn was cancelled while this approved tool call was running. It may have partially run; it was not retried.`;async function runApprovedCalls(e){let t={sequence:e.position.sequence,stepIndex:e.position.stepIndex,turnId:e.position.turnId},settleFailure=async(n,r,i)=>{let a=failedCall({callId:n,
|
|
1
|
+
import{asSchema}from"ai";import{createLogger,logError}from"#internal/logging.js";import{toError}from"#shared/errors.js";import{createActionPartialEvent,createActionResultEvent}from"#protocol/message.js";import{SEARCH_TOOL_NAME}from"#protocol/catalog-tools.js";import{toModelSchema}from"#tools/schema.js";import{parseJsonObject}from"#shared/json.js";import{toolCallModelOutput}from"#harness/tool-call-io.js";import{isAsyncIterable}from"#shared/async-iterable.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{createRuntimeToolResultFromValue}from"#harness/action-result-helpers.js";import{projectDeltaPresentation,projectResultPresentation}from"#harness/tool-presentation.js";import{isInlineAuthorizationToolResult}from"#harness/inline-tool-authorization.js";import{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,unavailableToolMessage}from"#harness/input-request-resolution.js";import{recheckApprovedCall,wrapToolExecute}from"#harness/tools.js";const log=createLogger(`harness.tool-loop`),APPROVED_CALL_INTERRUPTED_MESSAGE=`The turn was cancelled while this approved tool call was running. It may have partially run; it was not retried.`;async function runApprovedCalls(e){let t={sequence:e.position.sequence,stepIndex:e.position.stepIndex,turnId:e.position.turnId},settleFailure=async(n,r,i)=>{let a=failedCall({callId:n,failure:i,toolName:r});return await e.publish(createActionResultEvent({...t,result:a.result})),{part:a.part}},n=await Promise.allSettled(e.requests.map(async n=>{let r=[],i=[],{callId:a,toolName:o,input:s}=n.action,c=e.tools.get(o),l=c===void 0?void 0:wrapToolExecute(c),u=!1,d;try{if(throwIfTurnAborted(e.abortSignal),c===void 0||l===void 0)return{settled:[await settleFailure(a,o,unavailableToolMessage(o,e.tools.get(SEARCH_TOOL_NAME)!==void 0))],toolResults:i};if((await asSchema(toModelSchema(c.inputSchema,`input`)).validate?.(s))?.success===!1){let e=`The approved input is no longer valid for tool "${o}". Request a new tool call and approval.`;return{settled:[await settleFailure(a,o,e)],toolResults:i}}let f=await recheckApprovedCall(c,{abortSignal:e.abortSignal,callId:a,input:s,approvedTools:e.approvedTools});if(f.denied)return r.push(await rejectApprovedCall({request:n,reason:f.reason,position:t,publish:e.publish})),{settled:r,toolResults:i};let p,m,h=toolTelemetry(e.telemetry,{messages:[...e.messages],toolCall:{input:s,toolCallId:a,toolName:o,type:`tool-call`}});await h.started();let g=0;try{await h.execute(async()=>{let r=performance.now();try{u=!0;let r=e.responderOf(n),i=l(s,{...r!==void 0&&{approval:{responder:r}},abortSignal:e.abortSignal,messages:[...e.messages],toolCallId:a});if(isAsyncIterable(i))for await(let n of i)p=n,await e.publish(createActionPartialEvent({...t,presentation:projectDeltaPresentation(c,a,parseJsonObject(s),n),result:createRuntimeToolResultFromValue({callId:a,output:n,toolName:o})}));else p=await i}finally{g=performance.now()-r}})}catch(t){await h.ended({error:t,input:s,toolCallId:a,toolName:o,type:`tool-error`},g),throwIfTurnAborted(e.abortSignal),logError(log,`tool execution failed`,t,{toolName:o,toolCallId:a}),m=toError(t),p=m.message}m===void 0&&await h.ended({input:s,output:p,toolCallId:a,toolName:o,type:`tool-result`},g);let _={input:s,output:p,toolCallId:a,toolName:o,type:`tool-result`};return i.push(_),isInlineAuthorizationToolResult(_)?{settled:r,toolResults:i}:(d={part:{output:m===void 0?await toolCallModelOutput(c,p,a):{type:`error-text`,value:m.message},toolCallId:a,toolName:o,type:`tool-result`}},r.push(d),await e.publish(createActionResultEvent({...t,presentation:m===void 0?projectResultPresentation(c,a,parseJsonObject(s),p):void 0,result:createRuntimeToolResultFromValue({callId:a,isError:m!==void 0,output:m??p,toolName:o})})),{settled:r,toolResults:i})}catch(t){return e.abortSignal?.aborted===!0?(u||throwIfTurnAborted(e.abortSignal),d===void 0?{settled:[interruptedResult(a,o)],toolResults:i}:{settled:[d],toolResults:i}):(logError(log,`approved tool failed`,t,{toolName:o,toolCallId:a}),{settled:[await settleFailure(a,o,toError(t))],toolResults:i})}})),r=n.find(e=>e.status===`rejected`);if(r?.status===`rejected`&&e.abortSignal?.aborted!==!0)throw r.reason;let i=n.flatMap(e=>e.status===`fulfilled`?[e.value]:[]);return{settled:i.flatMap(e=>e.settled),toolResults:i.flatMap(e=>e.toolResults)}}function interruptedResult(e,t){return{part:{output:{type:`error-text`,value:APPROVED_CALL_INTERRUPTED_MESSAGE},toolCallId:e,toolName:t,type:`tool-result`}}}async function rejectApprovedCall(e){let{callId:t,toolName:n}=e.request.action;return await e.publish(createActionResultEvent({...e.position,rejected:!0,result:{callId:t,isError:!0,kind:`tool-result`,toolName:n,output:{code:`TOOL_EXECUTION_DENIED`,message:e.reason??TOOL_EXECUTION_DENIED_MESSAGE,tool:{result:`not_run`}}}})),{part:{output:{reason:e.reason,type:`execution-denied`},toolCallId:t,toolName:n,type:`tool-result`}}}function toolTelemetry(e,t){let n=e===void 0||e.isEnabled===!1?[]:[e.integrations??[]].flat(),r={...t,callId:`approved:${t.toolCall.toolCallId}`,functionId:e?.functionId,recordInputs:e?.recordInputs,recordOutputs:e?.recordOutputs,toolContext:void 0},notify=async e=>{await Promise.allSettled(n.map(async t=>await e(t)))};return{started:()=>notify(e=>e.onToolExecutionStart?.(r)),execute:async e=>{let wrapped=e;for(let e of n){if(e.executeTool===void 0)continue;let n=wrapped;wrapped=()=>e.executeTool({...r,execute:n,toolCallId:t.toolCall.toolCallId})}await wrapped()},ended:(e,t)=>notify(n=>n.onToolExecutionEnd?.({...r,toolExecutionMs:t,toolOutput:e}))}}export{APPROVED_CALL_INTERRUPTED_MESSAGE,rejectApprovedCall,runApprovedCalls};
|
|
@@ -32,7 +32,8 @@ export declare function unavailableToolMessage(toolName: string, searchable: boo
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function failedCall(call: {
|
|
34
34
|
readonly callId: string;
|
|
35
|
-
|
|
35
|
+
/** Why the call failed: the error it threw, or a message when it never ran. */
|
|
36
|
+
readonly failure: Error | string;
|
|
36
37
|
readonly toolName: string;
|
|
37
38
|
}): Required<SettledCall>;
|
|
38
39
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SEARCH_TOOL_NAME}from"#protocol/catalog-tools.js";import{createRuntimeToolResultFromValue}from"#harness/action-result-helpers.js";const TOOL_EXECUTION_DENIED_MESSAGE=`Tool execution was denied.`;function resolveInputOutcome(e,t){return e===`tool-approval`?resolveApprovalOutcome(t).status:t===void 0?`ignored`:`answered`}function resolveApprovalOutcome(e){if(e===void 0)return{approved:!1,reason:`Ignored because the user continued without responding.`,status:`ignored`};if(e.optionId===`approve`)return{approved:!0,reason:void 0,status:`approved`};if(e.optionId===`cancel`||e.optionId===`deny`){let t=e.text?.trim();return{approved:!1,reason:t?`${TOOL_EXECUTION_DENIED_MESSAGE} The person who denied it wrote: ${JSON.stringify(t)}`:TOOL_EXECUTION_DENIED_MESSAGE,status:`denied`}}return{approved:!1,reason:`Invalid approval response.`,status:`invalid`}}function unavailableToolMessage(e,t){return`The tool "${e}" is no longer available, so the call didn't run. If the task still needs it, ${t?`find an available tool with ${SEARCH_TOOL_NAME} and make a new call`:`make a new call with an available tool`}.`}function failedCall(e){let{callId:t,
|
|
1
|
+
import{toErrorMessage}from"#shared/errors.js";import{SEARCH_TOOL_NAME}from"#protocol/catalog-tools.js";import{createRuntimeToolResultFromValue}from"#harness/action-result-helpers.js";const TOOL_EXECUTION_DENIED_MESSAGE=`Tool execution was denied.`;function resolveInputOutcome(e,t){return e===`tool-approval`?resolveApprovalOutcome(t).status:t===void 0?`ignored`:`answered`}function resolveApprovalOutcome(e){if(e===void 0)return{approved:!1,reason:`Ignored because the user continued without responding.`,status:`ignored`};if(e.optionId===`approve`)return{approved:!0,reason:void 0,status:`approved`};if(e.optionId===`cancel`||e.optionId===`deny`){let t=e.text?.trim();return{approved:!1,reason:t?`${TOOL_EXECUTION_DENIED_MESSAGE} The person who denied it wrote: ${JSON.stringify(t)}`:TOOL_EXECUTION_DENIED_MESSAGE,status:`denied`}}return{approved:!1,reason:`Invalid approval response.`,status:`invalid`}}function unavailableToolMessage(e,t){return`The tool "${e}" is no longer available, so the call didn't run. If the task still needs it, ${t?`find an available tool with ${SEARCH_TOOL_NAME} and make a new call`:`make a new call with an available tool`}.`}function failedCall(e){let{callId:t,failure:n,toolName:r}=e;return{part:{output:{type:`error-text`,value:toErrorMessage(n)},toolCallId:t,toolName:r,type:`tool-result`},result:createRuntimeToolResultFromValue({callId:t,isError:!0,output:n,toolName:r})}}export{TOOL_EXECUTION_DENIED_MESSAGE,failedCall,resolveApprovalOutcome,resolveInputOutcome,unavailableToolMessage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{buildGatewayAttributionHeaders,withGatewayTraceContext}from"./model.js";import{isEmptyModelResponse,rethrowNoOutputAsEmptyResponse}from"./recovery.js";import{modelInstructions,requestMessages,withTrailingUserNote}from"./request.js";import{answerSkippedToolCalls,appendMissingToolResultMessages,extractToolResultCallIds,withAccumulatedResponseMessages}from"./response.js";import{runModelCallWithRetries}from"./retry.js";import{logToolExecutionError,prepareModelTools}from"./tools.js";import{extractGatewayCostUsd,extractTokenUsageDelta}from"./usage.js";import{ToolLoopAgent,isStepCount}from"ai";import{createLogger,logError}from"#internal/logging.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{REPLY_TOOL_NAME}from"#protocol/reply-tool.js";import{createStepCompletedEvent}from"#protocol/message.js";import{activeTurnId}from"#harness/session-machine/view.js";import{addTurnUsage}from"#harness/turn-tag-state.js";import{hydrateSandboxAttachments,moveToolResultFilesToUserMessages}from"#harness/attachment-staging.js";import{workingTaskIds}from"#execution/tasks/model-step.js";import{toEntryStep,toEntryStream,toEntryTelemetry}from"#harness/execute-call.js";import{discardAttempt}from"#harness/session-machine/transitions.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{summarizeKnownError}from"#harness/semantic-errors/index.js";import{estimateTokens}from"#harness/token-estimate.js";import{requireSessionModelReference}from"#harness/types.js";import{ContentFilteredModelResponseError,EmptyModelResponseError,ModelStreamStalledError}from"#harness/model-call/errors.js";import{resolveModelProfile}from"#harness/model-profile.js";import{estimateRequestEnvelope}from"#harness/request-envelope.js";import{interruptStreamOnFailure}from"#harness/interruptible-stream.js";import{buildToolApproval}from"#harness/tools.js";import{emitStreamContent}from"#harness/emission.js";import{compactPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";import{buildStepHooks,emitStepActions,readGatewayGenerationId}from"#harness/step-hooks.js";import{maybeCompact}from"#harness/compaction/step.js";const environment=process.env.NODE_ENV??`unknown`,log=createLogger(`harness.tool-loop`),MODEL_OUTPUT_TIMEOUT_MS=6e5;var ModelCaller=class{profile;attributionHeaders;projectedMessages;request;modelMessages=[];requestEnvelopeTokens=0;interruptedUsage;compactionFailure;attemptIndex=0;step;prompt;input;constructor(e,t,n){this.step=e,this.prompt=t,this.input=n,this.profile=resolveModelProfile(n.model,requireSessionModelReference(e.session).promptCache),this.attributionHeaders=buildGatewayAttributionHeaders(this.profile,e.config.runtimeIdentity),this.projectedMessages=n.projectedMessages,this.request=this.buildRequest()}async call(e){let t=new Map;return await runModelCallWithRetries(async n=>(n>1&&(await this.settleRetriedActions(t),t=new Map),await this.attempt({...e,suppressStepStartedEmission:n!==1||e.suppressStepStartedEmission},t)),{canRetry:()=>this.compactionFailure===void 0,sessionId:this.step.session.sessionId,turnId:this.step.position().turnId},this.input.generation.signal)}async settleRetriedActions(e){for(let[t,n]of e)await this.step.apply(discardAttempt(this.step.view(),{calls:[{callId:t,toolName:n}]})),e.delete(t)}throwIfCompactionFailed(){if(this.compactionFailure!==void 0)throw this.compactionFailure.error}async steered(){let{step:e}=this;return throwIfTurnAborted(e.config.abortSignal),e.ctx?.set(HistoryStateKey,this.request.historyState),this.interruptedUsage!==void 0&&(e.session=addTurnUsage(e.session,e.position().turnId,this.interruptedUsage)),await e.emit?.(createStepCompletedEvent({...e.position(),finishReason:`other`,usage:this.interruptedUsage})),{next:e.runStep,session:{...e.session,history:[...this.request.history]},steered:!0}}clearInterruptedUsage(){this.interruptedUsage=void 0}buildRequest(){return requestMessages(this.step,{catalog:this.input.catalog,hidesHeldText:this.input.hidesHeldText,messages:this.prompt.messages,pendingApprovalsNote:this.input.pendingApprovalsNote,projectedMessages:this.projectedMessages,turnMessages:this.input.turnMessages})}instructions(e){return modelInstructions({anthropicCache:this.profile.anthropicCache,extraSystemNote:e,session:this.step.session,systemMessages:this.request.systemMessages})}async prepare(e){let t=await prepareModelTools(this.step,{catalog:this.input.catalog,disabledProviderTools:e.disabledProviderTools,generation:this.input.generation,profile:this.profile});return this.request=this.buildRequest(),this.requestEnvelopeTokens=await estimateRequestEnvelope({history:this.projectedMessages,instructions:this.instructions(e.extraSystemNote),messages:withTrailingUserNote(this.request.nonSystemMessages,e.trailingUserNote),tools:t}),t}async compact(e,t){let{step:n,prompt:r}=this,{config:i}=n,a;try{if(a=await maybeCompact({abortSignal:i.abortSignal,auth:n.ctx?.get(AuthKey)??null,emissionState:n.position(),historyProjector:i.historyProjector,messages:[...r.messages],model:this.input.model,promptMessages:withClientContext(r),publish:n.publish,requestEnvelopeTokens:this.requestEnvelopeTokens,resolveModel:i.resolveModel,runtimeIdentity:i.runtimeIdentity,session:n.session,telemetry:n.instrumentation?.telemetry(),traceContextHeaders:n.instrumentation?.gatewayTraceContextHeaders}),a.failure!==void 0)throw a.failure.error}catch(e){throw this.compactionFailure={error:e},e}if(n.session=a.session,!a.compacted)return t;compactPrompt(n,r,a.messages);let{compaction:o}=n.session;return n.session={...n.session,compaction:{recentWindowSize:o.recentWindowSize,threshold:o.threshold,thresholdPercent:o.thresholdPercent}},this.projectedMessages=projectPrompt(n,r),await this.prepare(e)}async attempt(e,t){let{step:n}=this,{catalog:r,generation:i,model:a}=this.input,o=await this.compact(e,await this.prepare(e));this.requestEnvelopeTokens=Math.max(0,this.requestEnvelopeTokens-(estimateTokens(this.request.history)-estimateTokens(this.prompt.messages))),i.begin(),this.modelMessages=await hydrateSandboxAttachments(this.request.nonSystemMessages),this.profile.filesOutsideToolResults&&(this.modelMessages=moveToolResultFilesToUserMessages(this.modelMessages));let s=this.instructions(e.extraSystemNote),c=n.instrumentation?.resolveRuntimeContext({emissionState:n.position(),environment,modelInput:{instructions:s,messages:this.modelMessages},session:n.session})??{};e.retryReason&&(c[`eve.retry.reason`]=e.retryReason);let l=withTrailingUserNote(this.modelMessages,e.trailingUserNote),u=n.position(),d=n.instrumentation?.prepareAttempt({isFrameworkTool:e=>n.frameworkToolNames.has(e),attemptIndex:this.attemptIndex++,runtimeContext:c,stepIndex:u.stepIndex,turnId:activeTurnId(u)});this.input.setAttemptScope(d?.scope);let f=buildStepHooks({auth:n.ctx?.get(AuthKey)??null,profile:this.profile,session:n.session,startStep:e.suppressStepStartedEmission===!0?void 0:this.input.startStep}),p={headers:this.attributionHeaders,instructions:s,model:withGatewayTraceContext(a,this.profile,this.step.instrumentation?.gatewayTraceContextHeaders),onLanguageModelCallEnd:e=>{i.interrupted||(this.interruptedUsage=extractTokenUsageDelta({costUsd:extractGatewayCostUsd(e.providerMetadata),usage:e.usage}))},onToolExecutionEnd:e=>logToolExecutionError(e,r.resolve),onError(e){i.interrupted||summarizeKnownError(e.error)?.tags.includes(`config`)!==!0&&logError(log,`tool-loop stream error`,e.error)},onStepEnd:f.onStepEnd,onStepStart:f.onStepStart,prepareStep:f.prepareStep,reasoning:n.session.agent.modelReference?.reasoning??n.session.agent.reasoning,runtimeContext:c,stopWhen:isStepCount(1),telemetry:toEntryTelemetry(d?.telemetry,r.resolve),timeout:{chunkMs:MODEL_OUTPUT_TIMEOUT_MS,firstChunkMs:MODEL_OUTPUT_TIMEOUT_MS},toolApproval:buildToolApproval({abortSignal:i.signal,approvedTools:this.input.approvedTools,resolve:r.resolve}),tools:o},m=new ToolLoopAgent(p);try{let e=await this.stream(m,l,f.stepResult,t);return await d?.complete(),e}catch(e){if(i.interrupted?await d?.complete():await d?.fail(e),i.check(),isAbortError(e)&&!i.signal.aborted)throw new ModelStreamStalledError({cause:e});return rethrowNoOutputAsEmptyResponse(e)}}async stream(e,t,n,r){let{step:i}=this,{catalog:a,generation:o}=this.input,s=new Set([REPLY_TOOL_NAME]),c=await e.stream({abortSignal:o.signal,messages:t}),{emittedActionCallIds:l,handledInlineToolResultCallIds:u,invalidInputToolCallIds:d,inlineAuthorizationResults:f,trailingInlineToolResultParts:p}=await emitStreamContent(i.publish,i.position(),toEntryStream(interruptStreamOnFailure(c.fullStream,o.signal),a.resolve),{excludedActionToolNames:s,hidesHeldText:this.input.hidesHeldText&&workingTaskIds(i.session).length>0,tools:a,unsettledActionToolNames:r});throwIfTurnAborted(i.config.abortSignal),o.check();let[m,h]=toEntryStep(...await Promise.all([n,c.responseMessages]),a.resolve);assertUsableResponse(m,h,f.length>0||p.length>0);let g=answerSkippedToolCalls(m,a);await emitStepActions(i.publish,i.position(),g.length===0?m:withAccumulatedResponseMessages({stepResult:m,responseMessages:appendMissingToolResultMessages({append:g,responseMessages:m.response.messages})}),{emittedActionCallIds:l,excludedActionCallIds:d,excludedActionToolNames:s,handledInlineToolResultCallIds:u,tools:a});let _=new Map(m.toolResults.map(e=>[e.toolCallId,e]));for(let e of f)_.set(e.toolCallId,e);return withAccumulatedResponseMessages({invalidInputToolCallIds:d,responseMessages:appendMissingToolResultMessages({append:[...p,...answerSkippedToolCalls(m,a)],responseMessages:h}),stepResult:m,toolResults:[..._.values()]})}};function assertUsableResponse(e,t,n){if(e.finishReason===`content-filter`)throw new ContentFilteredModelResponseError(readGatewayGenerationId(e.providerMetadata));if(isEmptyModelResponse(e)&&extractToolResultCallIds(t).size===0&&!n)throw new EmptyModelResponseError}function isAbortError(e){return e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)}export{ModelCaller};
|
|
1
|
+
import{buildGatewayAttributionHeaders,withGatewayTraceContext}from"./model.js";import{isEmptyModelResponse,rethrowNoOutputAsEmptyResponse}from"./recovery.js";import{modelInstructions,requestMessages,withTrailingUserNote}from"./request.js";import{answerSkippedToolCalls,appendMissingToolResultMessages,extractToolResultCallIds,withAccumulatedResponseMessages}from"./response.js";import{runModelCallWithRetries}from"./retry.js";import{logToolExecutionError,prepareModelTools}from"./tools.js";import{extractGatewayCostUsd,extractTokenUsageDelta}from"./usage.js";import{ToolLoopAgent,isStepCount}from"ai";import{createLogger,logError}from"#internal/logging.js";import{AuthKey,HistoryStateKey}from"#context/keys.js";import{REPLY_TOOL_NAME}from"#protocol/reply-tool.js";import{createStepCompletedEvent}from"#protocol/message.js";import{activeTurnId}from"#harness/session-machine/view.js";import{addTurnUsage}from"#harness/turn-tag-state.js";import{hydrateSandboxAttachments,moveToolResultFilesToUserMessages}from"#harness/attachment-staging.js";import{workingTaskIds}from"#execution/tasks/model-step.js";import{toEntryStep,toEntryStream,toEntryTelemetry}from"#harness/execute-call.js";import{discardAttempt}from"#harness/session-machine/transitions.js";import{throwIfTurnAborted}from"#harness/turn-cancellation.js";import{summarizeKnownError}from"#harness/semantic-errors/index.js";import{estimateTokens}from"#harness/token-estimate.js";import{requireSessionModelReference}from"#harness/types.js";import{ContentFilteredModelResponseError,EmptyModelResponseError,ModelStreamStalledError}from"#harness/model-call/errors.js";import{resolveModelProfile}from"#harness/model-profile.js";import{estimateRequestEnvelope}from"#harness/request-envelope.js";import{interruptStreamOnFailure}from"#harness/interruptible-stream.js";import{buildToolApproval}from"#harness/tools.js";import{emitStreamContent}from"#harness/emission.js";import{compactPrompt,projectPrompt,withClientContext}from"#harness/step/prompt.js";import{buildStepHooks,emitStepActions,readGatewayGenerationId}from"#harness/step-hooks.js";import{maybeCompact}from"#harness/compaction/step.js";const environment=process.env.NODE_ENV??`unknown`,log=createLogger(`harness.tool-loop`),MODEL_OUTPUT_TIMEOUT_MS=6e5;var ModelCaller=class{profile;attributionHeaders;projectedMessages;request;modelMessages=[];requestEnvelopeTokens=0;interruptedUsage;compactionFailure;attemptIndex=0;step;prompt;input;constructor(e,t,n){this.step=e,this.prompt=t,this.input=n,this.profile=resolveModelProfile(n.model,requireSessionModelReference(e.session).promptCache),this.attributionHeaders=buildGatewayAttributionHeaders(this.profile,e.config.runtimeIdentity),this.projectedMessages=n.projectedMessages,this.request=this.buildRequest()}async call(e){let t=new Map;return await runModelCallWithRetries(async n=>(n>1&&(await this.settleRetriedActions(t),t=new Map),await this.attempt({...e,suppressStepStartedEmission:n!==1||e.suppressStepStartedEmission},t)),{canRetry:()=>this.compactionFailure===void 0,sessionId:this.step.session.sessionId,turnId:this.step.position().turnId},this.input.generation.signal)}async settleRetriedActions(e){for(let[t,n]of e)await this.step.apply(discardAttempt(this.step.view(),{calls:[{callId:t,toolName:n}]})),e.delete(t)}throwIfCompactionFailed(){if(this.compactionFailure!==void 0)throw this.compactionFailure.error}async steered(){let{step:e}=this;return throwIfTurnAborted(e.config.abortSignal),e.ctx?.set(HistoryStateKey,this.request.historyState),this.interruptedUsage!==void 0&&(e.session=addTurnUsage(e.session,e.position().turnId,this.interruptedUsage)),await e.emit?.(createStepCompletedEvent({...e.position(),finishReason:`other`,usage:this.interruptedUsage})),{next:e.runStep,session:{...e.session,history:[...this.request.history]},steered:!0}}clearInterruptedUsage(){this.interruptedUsage=void 0}buildRequest(){return requestMessages(this.step,{catalog:this.input.catalog,hidesHeldText:this.input.hidesHeldText,messages:this.prompt.messages,pendingApprovalsNote:this.input.pendingApprovalsNote,projectedMessages:this.projectedMessages,turnMessages:this.input.turnMessages})}instructions(e){return modelInstructions({anthropicCache:this.profile.anthropicCache,extraSystemNote:e,session:this.step.session,systemMessages:this.request.systemMessages})}async prepare(e){let t=await prepareModelTools(this.step,{catalog:this.input.catalog,disabledProviderTools:e.disabledProviderTools,generation:this.input.generation,profile:this.profile});return this.request=this.buildRequest(),this.requestEnvelopeTokens=await estimateRequestEnvelope({history:this.projectedMessages,instructions:this.instructions(e.extraSystemNote),messages:withTrailingUserNote(this.request.nonSystemMessages,e.trailingUserNote),tools:t}),t}async compact(e,t){let{step:n,prompt:r}=this,{config:i}=n,a;try{if(a=await maybeCompact({abortSignal:i.abortSignal,auth:n.ctx?.get(AuthKey)??null,emissionState:n.position(),historyProjector:i.historyProjector,messages:[...r.messages],model:this.input.model,promptMessages:withClientContext(r),publish:n.publish,requestEnvelopeTokens:this.requestEnvelopeTokens,resolveModel:i.resolveModel,runtimeIdentity:i.runtimeIdentity,session:n.session,telemetry:n.instrumentation?.telemetry(),traceContextHeaders:n.instrumentation?.gatewayTraceContextHeaders}),a.failure!==void 0)throw a.failure.error}catch(e){throw this.compactionFailure={error:e},e}if(n.session=a.session,!a.compacted)return t;compactPrompt(n,r,a.messages);let{compaction:o}=n.session;return n.session={...n.session,compaction:{recentWindowSize:o.recentWindowSize,threshold:o.threshold,thresholdPercent:o.thresholdPercent}},this.projectedMessages=projectPrompt(n,r),await this.prepare(e)}async attempt(e,t){let{step:n}=this,{catalog:r,generation:i,model:a}=this.input,o=await this.compact(e,await this.prepare(e));this.requestEnvelopeTokens=Math.max(0,this.requestEnvelopeTokens-(estimateTokens(this.request.history)-estimateTokens(this.prompt.messages))),i.begin(),this.modelMessages=await hydrateSandboxAttachments(this.request.nonSystemMessages),this.profile.filesOutsideToolResults&&(this.modelMessages=moveToolResultFilesToUserMessages(this.modelMessages));let s=this.instructions(e.extraSystemNote),c=n.instrumentation?.resolveRuntimeContext({emissionState:n.position(),environment,modelInput:{instructions:s,messages:this.modelMessages},session:n.session})??{};e.retryReason&&(c[`eve.retry.reason`]=e.retryReason);let l=withTrailingUserNote(this.modelMessages,e.trailingUserNote),u=n.position(),d=n.instrumentation?.prepareAttempt({isFrameworkTool:e=>n.frameworkToolNames.has(e),attemptIndex:this.attemptIndex++,runtimeContext:c,stepIndex:u.stepIndex,turnId:activeTurnId(u)});this.input.setAttemptScope(d?.scope);let f=buildStepHooks({auth:n.ctx?.get(AuthKey)??null,profile:this.profile,session:n.session,startStep:e.suppressStepStartedEmission===!0?void 0:this.input.startStep}),p={headers:this.attributionHeaders,instructions:s,model:withGatewayTraceContext(a,this.profile,this.step.instrumentation?.gatewayTraceContextHeaders),onLanguageModelCallEnd:e=>{i.interrupted||(this.interruptedUsage=extractTokenUsageDelta({costUsd:extractGatewayCostUsd(e.providerMetadata),usage:e.usage}))},onToolExecutionEnd:e=>logToolExecutionError(e,r.resolve),onError(e){i.interrupted||summarizeKnownError(e.error)?.tags.includes(`config`)!==!0&&logError(log,`tool-loop stream error`,e.error)},onStepEnd:f.onStepEnd,onStepStart:f.onStepStart,prepareStep:f.prepareStep,reasoning:n.session.agent.modelReference?.reasoning??n.session.agent.reasoning,runtimeContext:c,stopWhen:isStepCount(1),telemetry:toEntryTelemetry(d?.telemetry,r.resolve),timeout:{chunkMs:MODEL_OUTPUT_TIMEOUT_MS,firstChunkMs:MODEL_OUTPUT_TIMEOUT_MS},toolApproval:buildToolApproval({abortSignal:i.signal,approvedTools:this.input.approvedTools,resolve:r.resolve}),tools:o},m=new ToolLoopAgent(p);try{let e=await this.stream(m,l,f.stepResult,t);return await d?.complete(),e}catch(e){if(i.interrupted?await d?.complete():await d?.fail(e),i.check(),isAbortError(e)&&!i.signal.aborted)throw new ModelStreamStalledError({cause:e});return rethrowNoOutputAsEmptyResponse(e)}}async stream(e,t,n,r){let{step:i}=this,{catalog:a,generation:o}=this.input,s=new Set([REPLY_TOOL_NAME]),c=await e.stream({abortSignal:o.signal,messages:t}),{emittedActionCallIds:l,handledInlineToolResultCallIds:u,invalidInputToolCallIds:d,inlineAuthorizationResults:f,trailingInlineToolResultParts:p}=await emitStreamContent(i.publish,i.position(),toEntryStream(interruptStreamOnFailure(c.fullStream,o.signal),a.resolve),{excludedActionToolNames:s,hidesHeldText:this.input.hidesHeldText&&workingTaskIds(i.session).length>0,tools:a,unsettledActionToolNames:r});throwIfTurnAborted(i.config.abortSignal),o.check();let[m,h]=toEntryStep(...await Promise.all([n,c.responseMessages]),a.resolve);assertUsableResponse(m,h,{allowEmptyStop:!i.hasDelegatedCaller,hasInlineResults:f.length>0||p.length>0});let g=answerSkippedToolCalls(m,a);await emitStepActions(i.publish,i.position(),g.length===0?m:withAccumulatedResponseMessages({stepResult:m,responseMessages:appendMissingToolResultMessages({append:g,responseMessages:m.response.messages})}),{emittedActionCallIds:l,excludedActionCallIds:d,excludedActionToolNames:s,handledInlineToolResultCallIds:u,tools:a});let _=new Map(m.toolResults.map(e=>[e.toolCallId,e]));for(let e of f)_.set(e.toolCallId,e);return withAccumulatedResponseMessages({invalidInputToolCallIds:d,responseMessages:appendMissingToolResultMessages({append:[...p,...answerSkippedToolCalls(m,a)],responseMessages:h}),stepResult:m,toolResults:[..._.values()]})}};function assertUsableResponse(e,t,n){if(e.finishReason===`content-filter`)throw new ContentFilteredModelResponseError(readGatewayGenerationId(e.providerMetadata));if(!(n.allowEmptyStop&&e.finishReason===`stop`)&&isEmptyModelResponse(e)&&extractToolResultCallIds(t).size===0&&!n.hasInlineResults)throw new EmptyModelResponseError}function isAbortError(e){return e instanceof Error&&(e.name===`AbortError`||e.name===`TimeoutError`)}export{ModelCaller};
|