eve 0.77.0 → 0.78.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 +16 -0
- package/dist/src/compiled/.vendor-stamp.json +1 -1
- package/dist/src/context/keys.d.ts +16 -0
- package/dist/src/context/keys.js +1 -1
- package/dist/src/execution/agent-sessions/steps.d.ts +2 -0
- package/dist/src/execution/agent-sessions/steps.js +1 -1
- package/dist/src/execution/cancelled-model-call-batch.js +1 -1
- package/dist/src/execution/catalog/search.js +1 -1
- package/dist/src/execution/catalog/step-catalog.d.ts +12 -3
- package/dist/src/execution/catalog/step-catalog.js +1 -1
- package/dist/src/execution/coordination-dispatch-shared.d.ts +1 -2
- package/dist/src/execution/coordination-dispatch-shared.js +1 -1
- package/dist/src/execution/coordination-dispatch-step.js +1 -1
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-container.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/just-bash.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-lifecycle.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/sandbox/session.d.ts +6 -0
- package/dist/src/execution/sandbox/session.js +2 -2
- package/dist/src/execution/session/active-turn.d.ts +9 -1
- package/dist/src/execution/session/active-turn.js +1 -1
- package/dist/src/execution/session/checkpoint-migrations.js +1 -1
- package/dist/src/execution/session/handoff.d.ts +1 -1
- package/dist/src/execution/session/handoff.js +1 -1
- package/dist/src/execution/session/next-input.js +1 -1
- package/dist/src/execution/session/turn.d.ts +11 -4
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-inbox/inbox.d.ts +3 -0
- package/dist/src/execution/session-inbox/inbox.js +1 -1
- package/dist/src/execution/session-workflow-tool-run.d.ts +14 -12
- package/dist/src/execution/session-workflow-tool-run.js +1 -1
- package/dist/src/execution/tasks/start.d.ts +14 -1
- package/dist/src/execution/tasks/start.js +1 -1
- package/dist/src/execution/tasks/steps.d.ts +7 -4
- package/dist/src/execution/tasks/steps.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 +20 -0
- package/dist/src/execution/tools/workflow/apply-run-messages-step.js +1 -0
- package/dist/src/execution/tools/workflow/ask.d.ts +0 -1
- package/dist/src/execution/tools/workflow/ask.js +1 -1
- package/dist/src/execution/tools/workflow/interrupt.d.ts +5 -2
- package/dist/src/execution/tools/workflow/interrupt.js +1 -1
- package/dist/src/execution/tools/workflow/messages.d.ts +14 -0
- package/dist/src/execution/tools/workflow/messages.js +1 -1
- package/dist/src/execution/tools/workflow/owner.d.ts +18 -6
- package/dist/src/execution/tools/workflow/owner.js +1 -1
- package/dist/src/execution/tools/workflow/start.d.ts +10 -0
- package/dist/src/execution/tools/workflow/start.js +1 -1
- package/dist/src/execution/tools/workflow/step.js +1 -1
- package/dist/src/execution/tools/workflow/workflow-owner-blocking.d.ts +12 -0
- package/dist/src/execution/tools/workflow/workflow-owner-blocking.js +1 -1
- package/dist/src/execution/tools/workflow/workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.d.ts +18 -3
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/harness/hitl/approvals.d.ts +4 -7
- package/dist/src/harness/hitl/approvals.js +1 -1
- package/dist/src/harness/hitl/approved-calls.d.ts +11 -0
- package/dist/src/harness/hitl/approved-calls.js +1 -1
- package/dist/src/harness/hitl/candidates.d.ts +0 -4
- package/dist/src/harness/hitl/candidates.js +1 -1
- package/dist/src/harness/hitl/delivery.d.ts +0 -1
- package/dist/src/harness/hitl/delivery.js +1 -1
- package/dist/src/harness/hitl/index.d.ts +2 -2
- package/dist/src/harness/hitl/index.js +1 -1
- package/dist/src/harness/hitl/intake.d.ts +2 -2
- package/dist/src/harness/hitl/intake.js +1 -1
- package/dist/src/harness/model-call/call.js +1 -1
- package/dist/src/harness/model-call/run.js +1 -1
- package/dist/src/harness/session-machine/state.d.ts +0 -2
- package/dist/src/harness/session-machine/view.d.ts +0 -3
- package/dist/src/harness/session-machine/view.js +1 -1
- package/dist/src/harness/step/after-model.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/stamped-package-version.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/tools/provided/ask-question-workflow.js +1 -1
- package/dist/src/tools/provided/sleep-workflow.js +1 -1
- package/docs/agent-config.md +12 -4
- package/docs/concepts/built-in-tools.md +9 -9
- package/docs/guides/dynamic-capabilities.md +6 -2
- package/docs/sandbox/index.mdx +2 -0
- package/docs/tools/human-in-the-loop.md +1 -1
- package/package.json +1 -1
- package/dist/src/context/caller-scope.d.ts +0 -7
- package/dist/src/context/caller-scope.js +0 -1
- package/dist/src/execution/tools/workflow/emit-workflow-tool-run-report-step.d.ts +0 -13
- package/dist/src/execution/tools/workflow/emit-workflow-tool-run-report-step.js +0 -1
- package/dist/src/harness/hitl/approved-call-callers.d.ts +0 -14
- package/dist/src/harness/hitl/approved-call-callers.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.78.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9559de8: Approved calls now always run as the requester. This closes a privilege escalation: when another person approved a call, it ran with the approver's identity and credentials, so a requester could get a tool to act with access they don't have. The call now keeps the identity and credentials of the person whose turn requested it, and approved workflow and agent calls are rechecked before dispatch. This reverses the execution-identity rule from #4368. Tools that should only proceed for certain approvers can still check `response.principal` in their `approval.response` policy.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- db71190: A dynamic resolver no longer adds the catalog tools (`eve__search`, `eve__tool`, and `eve__skill`) on its own. eve adds the catalog tools once a session reaches something they find, call, or load, such as a deferred entry a resolver returns, and keeps them for the rest of the session. Agents whose resolvers return only listed tools no longer see these tools or spend steps searching.
|
|
12
|
+
- 4ef1ad9: Workflow tools and the agents they open start faster. Tasks begin work sooner, `ctx.agent().send()` no longer waits for the agent's session to boot, a model step that starts several workflow tool runs starts them in parallel, and a fan-out's agent starts, progress, and results reach the session in batches instead of one at a time.
|
|
13
|
+
- f3dbd0c: Keep an over-budget turn waiting for input until its continuation question is answered. Continue resumes the same turn, queued messages wait for the answer, and cancellation withdraws the question.
|
|
14
|
+
- 7f87e28: Emit sign-in requests for executing tools even when a sibling call in the same model step needs approval.
|
|
15
|
+
- 3e7bbb2: Emit `turn.waiting` with `on: "tasks"` when a model step parks on blocking workflow execute calls, including calls dispatched after approval. Task and agent receipt dispatches do not emit a wait; their actual task waits report the park.
|
|
16
|
+
- 3445e89: Sandbox commands now run with `AI_AGENT=eve` by default, so agent-aware CLIs such as `vercel` switch to their non-interactive agent mode. Set `AI_AGENT` in the environment's `env` option, or in the `env` of one `run()` or `spawn()` call, to override it.
|
|
17
|
+
- db71190: `eve__search` results now include `searched`, the number of entries the query covered, and `remaining`, the number of matches past `limit`, so the model can tell after one search how much is left to find. Its description now tells the model to search only when nothing in its tool list fits the request.
|
|
18
|
+
|
|
3
19
|
## 0.77.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"zod": "4.5.4",
|
|
60
60
|
"zod-validation-error": "5.0.0"
|
|
61
61
|
},
|
|
62
|
-
"scriptHash": "
|
|
62
|
+
"scriptHash": "f296c8787cbb975a01596e49048f5c4b1a1480c03754134647da5eff762b98ca",
|
|
63
63
|
"toolVersions": {
|
|
64
64
|
"rolldown": "1.2.9",
|
|
65
65
|
"typescript": "7.0.2"
|
|
@@ -83,6 +83,22 @@ export interface HistoryState {
|
|
|
83
83
|
readonly announcements?: Readonly<Record<string, string>>;
|
|
84
84
|
}
|
|
85
85
|
export declare const HistoryStateKey: ContextKey<HistoryState>;
|
|
86
|
+
/**
|
|
87
|
+
* The catalog tools a session's tool list has offered. Each stays offered for
|
|
88
|
+
* the rest of the session, so the tool list never drops a catalog tool that
|
|
89
|
+
* earlier calls named. Compaction keeps it, unlike {@link HistoryStateKey}.
|
|
90
|
+
*/
|
|
91
|
+
export interface OfferedCatalogTools {
|
|
92
|
+
/** `eve__tool` mentions connected services, and `eve__search` their sign-in entries. */
|
|
93
|
+
readonly connections: boolean;
|
|
94
|
+
/** `eve__search` finds skills. */
|
|
95
|
+
readonly searchableSkills: boolean;
|
|
96
|
+
/** `eve__skill`. */
|
|
97
|
+
readonly skills: boolean;
|
|
98
|
+
/** `eve__tool`. */
|
|
99
|
+
readonly tools: boolean;
|
|
100
|
+
}
|
|
101
|
+
export declare const OfferedCatalogToolsKey: ContextKey<OfferedCatalogTools>;
|
|
86
102
|
export interface ActiveChannelDelivery {
|
|
87
103
|
readonly traceSessionId: string;
|
|
88
104
|
readonly agentName?: string;
|
package/dist/src/context/keys.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SESSION_INBOX_CONTEXT_KEY}from"#execution/session-inbox/address.js";import{ContextKey}from"#context/key.js";import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{SESSION_CALLBACK_CONTEXT_KEY_NAME}from"#context/key-names.js";const AuthKey=new ContextKey(`eve.auth`),ToolStubsKey=new ContextKey(STUB_CONTEXT_KEY),InitiatorAuthKey=new ContextKey(`eve.initiatorAuth`),SessionIdKey=new ContextKey(`eve.sessionId`),ConversationIdKey=new ContextKey(`eve.conversationId`),SessionInboxKey=new ContextKey(SESSION_INBOX_CONTEXT_KEY),ContinuationTokenKey=new ContextKey(`eve.continuationToken`),ContinuationHookTokensKey=new ContextKey(`eve.continuationHookTokens`),ChannelRequestIdKey=new ContextKey(`eve.channelRequestId`),LocalDevRequestKey=new ContextKey(`eve.internal.localDevRequest`),OccurrenceIdKey=new ContextKey(`eve.scheduleOccurrenceId`),ScheduleIdKey=new ContextKey(`eve.scheduleId`),ScheduleInstanceKey=new ContextKey(`eve.scheduleInstance`),SessionTitleKey=new ContextKey(`eve.sessionTitle`),ChannelDeliveryKey=new ContextKey(`eve.channelDelivery`),TurnDeliveryIdsKey=new ContextKey(`eve.turnDeliveryIds`),HistoryStateKey=new ContextKey(`eve.historyState`),ActiveChannelDeliveriesKey=new ContextKey(`eve.activeChannelDeliveries`),ChannelInstrumentationKey=new ContextKey(`eve.channelInstrumentation`),ParentSessionKey=new ContextKey(`eve.parentSession`),SessionPredecessorKey=new ContextKey(`eve.sessionPredecessor`),TraceRootKey=new ContextKey(`eve.traceRoot`),ParentTraceContextKey=new ContextKey(`eve.parentTraceContext`),SessionTraceSeedKey=new ContextKey(`eve.sessionTraceSeed`),OtelTraceEnabledKey=new ContextKey(`eve.otelTraceEnabled`),CapabilitiesKey=new ContextKey(`eve.capabilities`),SessionCallbackKey=new ContextKey(SESSION_CALLBACK_CONTEXT_KEY_NAME),LegacyRemoteAgentCallerKey=new ContextKey(`eve.legacyRemoteAgentCaller`),SessionKey=new ContextKey(`eve.session`),SandboxKey=new ContextKey(`eve.sandbox`),SandboxTerminalCleanupKey=new ContextKey(`eve.internal.sandboxTerminalCleanup`),HandleEventKey=new ContextKey(`eve.internal.handleEvent`),StaticModelReferenceKey=new ContextKey(`eve.staticModelReference`),SessionDynamicModelReferenceKey=new ContextKey(`eve.sessionDynamicModelReference`),TurnDynamicModelReferenceKey=new ContextKey(`eve.turnDynamicModelReference`),RuntimeModelMetadataCacheKey=new ContextKey(`eve.runtimeModelMetadataCache`),LiveStepDynamicModelSelectionKey=new ContextKey(`eve.liveStepDynamicModelSelection`),SessionDynamicToolMetadataKey=new ContextKey(`eve.sessionDynamicToolMetadata`),SessionDynamicToolRuntimeRevisionKey=new ContextKey(`eve.sessionDynamicToolRuntimeRevision`),TurnDynamicToolMetadataKey=new ContextKey(`eve.turnDynamicToolMetadata`),TurnMemoryLocksKey=new ContextKey(`eve.memory.turnLocks`),PreparedMemoryPreambleKey=new ContextKey(`eve.memory.preparedPreamble`),PendingMemoryCommitKey=new ContextKey(`eve.memory.pendingCommit`),PreparedMemoryCompactionKey=new ContextKey(`eve.memory.preparedCompaction`),StepDynamicToolMetadataKey=new ContextKey(`eve.stepDynamicToolMetadata`),SessionDynamicSubagentSelectionsKey=new ContextKey(`eve.sessionDynamicSubagentSelections`),TurnDynamicSubagentSelectionsKey=new ContextKey(`eve.turnDynamicSubagentSelections`),SessionDynamicSubagentRuntimeRevisionKey=new ContextKey(`eve.sessionDynamicSubagentRuntimeRevision`),DynamicSubagentAgentConfigKey=new ContextKey(`eve.dynamicSubagentAgentConfig`),DynamicSkillManifestKey=new ContextKey(`eve.dynamicSkillManifest`),DynamicSkillSandboxKey=new ContextKey(`eve.dynamicSkillSandbox`),SessionDynamicInstructionsKey=new ContextKey(`eve.sessionDynamicInstructions`),TurnDynamicInstructionsKey=new ContextKey(`eve.turnDynamicInstructions`),DynamicInstructionResolveMessagesKey=new ContextKey(`eve.dynamicInstructionResolveMessages`),PendingDynamicInstructionUserMessagesKey=new ContextKey(`eve.pendingDynamicInstructionUserMessages`);export{ActiveChannelDeliveriesKey,AuthKey,CapabilitiesKey,ChannelDeliveryKey,ChannelInstrumentationKey,ChannelRequestIdKey,ContinuationHookTokensKey,ContinuationTokenKey,ConversationIdKey,DynamicInstructionResolveMessagesKey,DynamicSkillManifestKey,DynamicSkillSandboxKey,DynamicSubagentAgentConfigKey,HandleEventKey,HistoryStateKey,InitiatorAuthKey,LegacyRemoteAgentCallerKey,LiveStepDynamicModelSelectionKey,LocalDevRequestKey,OccurrenceIdKey,OtelTraceEnabledKey,ParentSessionKey,ParentTraceContextKey,PendingDynamicInstructionUserMessagesKey,PendingMemoryCommitKey,PreparedMemoryCompactionKey,PreparedMemoryPreambleKey,RuntimeModelMetadataCacheKey,SandboxKey,SandboxTerminalCleanupKey,ScheduleIdKey,ScheduleInstanceKey,SessionCallbackKey,SessionDynamicInstructionsKey,SessionDynamicModelReferenceKey,SessionDynamicSubagentRuntimeRevisionKey,SessionDynamicSubagentSelectionsKey,SessionDynamicToolMetadataKey,SessionDynamicToolRuntimeRevisionKey,SessionIdKey,SessionInboxKey,SessionKey,SessionPredecessorKey,SessionTitleKey,SessionTraceSeedKey,StaticModelReferenceKey,StepDynamicToolMetadataKey,ToolStubsKey,TraceRootKey,TurnDeliveryIdsKey,TurnDynamicInstructionsKey,TurnDynamicModelReferenceKey,TurnDynamicSubagentSelectionsKey,TurnDynamicToolMetadataKey,TurnMemoryLocksKey};
|
|
1
|
+
import{SESSION_INBOX_CONTEXT_KEY}from"#execution/session-inbox/address.js";import{ContextKey}from"#context/key.js";import{STUB_CONTEXT_KEY}from"#tool-stubs/types.js";import{SESSION_CALLBACK_CONTEXT_KEY_NAME}from"#context/key-names.js";const AuthKey=new ContextKey(`eve.auth`),ToolStubsKey=new ContextKey(STUB_CONTEXT_KEY),InitiatorAuthKey=new ContextKey(`eve.initiatorAuth`),SessionIdKey=new ContextKey(`eve.sessionId`),ConversationIdKey=new ContextKey(`eve.conversationId`),SessionInboxKey=new ContextKey(SESSION_INBOX_CONTEXT_KEY),ContinuationTokenKey=new ContextKey(`eve.continuationToken`),ContinuationHookTokensKey=new ContextKey(`eve.continuationHookTokens`),ChannelRequestIdKey=new ContextKey(`eve.channelRequestId`),LocalDevRequestKey=new ContextKey(`eve.internal.localDevRequest`),OccurrenceIdKey=new ContextKey(`eve.scheduleOccurrenceId`),ScheduleIdKey=new ContextKey(`eve.scheduleId`),ScheduleInstanceKey=new ContextKey(`eve.scheduleInstance`),SessionTitleKey=new ContextKey(`eve.sessionTitle`),ChannelDeliveryKey=new ContextKey(`eve.channelDelivery`),TurnDeliveryIdsKey=new ContextKey(`eve.turnDeliveryIds`),HistoryStateKey=new ContextKey(`eve.historyState`),OfferedCatalogToolsKey=new ContextKey(`eve.offeredCatalogTools`),ActiveChannelDeliveriesKey=new ContextKey(`eve.activeChannelDeliveries`),ChannelInstrumentationKey=new ContextKey(`eve.channelInstrumentation`),ParentSessionKey=new ContextKey(`eve.parentSession`),SessionPredecessorKey=new ContextKey(`eve.sessionPredecessor`),TraceRootKey=new ContextKey(`eve.traceRoot`),ParentTraceContextKey=new ContextKey(`eve.parentTraceContext`),SessionTraceSeedKey=new ContextKey(`eve.sessionTraceSeed`),OtelTraceEnabledKey=new ContextKey(`eve.otelTraceEnabled`),CapabilitiesKey=new ContextKey(`eve.capabilities`),SessionCallbackKey=new ContextKey(SESSION_CALLBACK_CONTEXT_KEY_NAME),LegacyRemoteAgentCallerKey=new ContextKey(`eve.legacyRemoteAgentCaller`),SessionKey=new ContextKey(`eve.session`),SandboxKey=new ContextKey(`eve.sandbox`),SandboxTerminalCleanupKey=new ContextKey(`eve.internal.sandboxTerminalCleanup`),HandleEventKey=new ContextKey(`eve.internal.handleEvent`),StaticModelReferenceKey=new ContextKey(`eve.staticModelReference`),SessionDynamicModelReferenceKey=new ContextKey(`eve.sessionDynamicModelReference`),TurnDynamicModelReferenceKey=new ContextKey(`eve.turnDynamicModelReference`),RuntimeModelMetadataCacheKey=new ContextKey(`eve.runtimeModelMetadataCache`),LiveStepDynamicModelSelectionKey=new ContextKey(`eve.liveStepDynamicModelSelection`),SessionDynamicToolMetadataKey=new ContextKey(`eve.sessionDynamicToolMetadata`),SessionDynamicToolRuntimeRevisionKey=new ContextKey(`eve.sessionDynamicToolRuntimeRevision`),TurnDynamicToolMetadataKey=new ContextKey(`eve.turnDynamicToolMetadata`),TurnMemoryLocksKey=new ContextKey(`eve.memory.turnLocks`),PreparedMemoryPreambleKey=new ContextKey(`eve.memory.preparedPreamble`),PendingMemoryCommitKey=new ContextKey(`eve.memory.pendingCommit`),PreparedMemoryCompactionKey=new ContextKey(`eve.memory.preparedCompaction`),StepDynamicToolMetadataKey=new ContextKey(`eve.stepDynamicToolMetadata`),SessionDynamicSubagentSelectionsKey=new ContextKey(`eve.sessionDynamicSubagentSelections`),TurnDynamicSubagentSelectionsKey=new ContextKey(`eve.turnDynamicSubagentSelections`),SessionDynamicSubagentRuntimeRevisionKey=new ContextKey(`eve.sessionDynamicSubagentRuntimeRevision`),DynamicSubagentAgentConfigKey=new ContextKey(`eve.dynamicSubagentAgentConfig`),DynamicSkillManifestKey=new ContextKey(`eve.dynamicSkillManifest`),DynamicSkillSandboxKey=new ContextKey(`eve.dynamicSkillSandbox`),SessionDynamicInstructionsKey=new ContextKey(`eve.sessionDynamicInstructions`),TurnDynamicInstructionsKey=new ContextKey(`eve.turnDynamicInstructions`),DynamicInstructionResolveMessagesKey=new ContextKey(`eve.dynamicInstructionResolveMessages`),PendingDynamicInstructionUserMessagesKey=new ContextKey(`eve.pendingDynamicInstructionUserMessages`);export{ActiveChannelDeliveriesKey,AuthKey,CapabilitiesKey,ChannelDeliveryKey,ChannelInstrumentationKey,ChannelRequestIdKey,ContinuationHookTokensKey,ContinuationTokenKey,ConversationIdKey,DynamicInstructionResolveMessagesKey,DynamicSkillManifestKey,DynamicSkillSandboxKey,DynamicSubagentAgentConfigKey,HandleEventKey,HistoryStateKey,InitiatorAuthKey,LegacyRemoteAgentCallerKey,LiveStepDynamicModelSelectionKey,LocalDevRequestKey,OccurrenceIdKey,OfferedCatalogToolsKey,OtelTraceEnabledKey,ParentSessionKey,ParentTraceContextKey,PendingDynamicInstructionUserMessagesKey,PendingMemoryCommitKey,PreparedMemoryCompactionKey,PreparedMemoryPreambleKey,RuntimeModelMetadataCacheKey,SandboxKey,SandboxTerminalCleanupKey,ScheduleIdKey,ScheduleInstanceKey,SessionCallbackKey,SessionDynamicInstructionsKey,SessionDynamicModelReferenceKey,SessionDynamicSubagentRuntimeRevisionKey,SessionDynamicSubagentSelectionsKey,SessionDynamicToolMetadataKey,SessionDynamicToolRuntimeRevisionKey,SessionIdKey,SessionInboxKey,SessionKey,SessionPredecessorKey,SessionTitleKey,SessionTraceSeedKey,StaticModelReferenceKey,StepDynamicToolMetadataKey,ToolStubsKey,TraceRootKey,TurnDeliveryIdsKey,TurnDynamicInstructionsKey,TurnDynamicModelReferenceKey,TurnDynamicSubagentSelectionsKey,TurnDynamicToolMetadataKey,TurnMemoryLocksKey};
|
|
@@ -7,6 +7,8 @@ export type AgentSessionAddress = {
|
|
|
7
7
|
readonly name: string;
|
|
8
8
|
readonly nodeId: string;
|
|
9
9
|
readonly sessionId: string;
|
|
10
|
+
/** Names the session to whichever run holds its inbox. */
|
|
11
|
+
readonly continuationToken: string;
|
|
10
12
|
} | {
|
|
11
13
|
readonly callbackBaseUrl: string;
|
|
12
14
|
readonly kind: "remote";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger,logError}from"#internal/logging.js";import{sessionInboxHookToken}from"#execution/session-inbox/address.js";import{ContextContainer,contextStorage}from"#context/container.js";import{createEveCallbackRoutePath}from"#protocol/routes.js";import{SessionStrandedError}from"#channel/session-stranded-error.js";import{createWorkflowRuntime,dispatchWorkflowSessionCommand,
|
|
1
|
+
import{createLogger,logError}from"#internal/logging.js";import{sessionInboxHookToken}from"#execution/session-inbox/address.js";import{ContextContainer,contextStorage}from"#context/container.js";import{createEveCallbackRoutePath}from"#protocol/routes.js";import{SessionStrandedError}from"#channel/session-stranded-error.js";import{createWorkflowRuntime,dispatchWorkflowSessionCommand,resolveContinuation,waitForCommandHookOwner,waitForSessionInbox}from"#execution/workflow-runtime.js";import{resolveDurableCompiledArtifactsSource}from"#runtime/durable-compiled-artifacts-source.js";import{getStepMetadata,getWorkflowMetadata}from"#compiled/@workflow/core/index.js";import{createWorkflowCallbackUrl,resolveWorkflowCallbackBaseUrl}from"#execution/workflow-callback-url.js";import{resolveAgentAction,resolveAgentStartTarget}from"#execution/agent-sessions/target.js";import{getCompiledRuntimeAgentBundle}from"#runtime/sessions/compiled-agent-cache.js";import{cancelRemoteAgentTurn,continueRemoteAgentSession,resetRemoteAgentSession,resolveRemoteAgentForAction,startRemoteAgentSession}from"#execution/agent-sessions/remote.js";import{buildSubagentRunInput}from"#subagents/tool.js";import{resolveConversationId}from"#shared/conversation-identity.js";import{stubToolPath}from"#tool-stubs/target.js";const log=createLogger(`execution.agent-sessions`),RUN_FINISHED_REASON=`The workflow run that opened this session finished.`;async function openAgentSessionStep(e){"use step";let{context:t}=e,n=await loadAgentSessionBundle(t),r=resolveAgentAction({bundle:n,callId:t.parent.callId,dynamicSelections:t.dynamicSelections,input:{message:e.message,outputSchema:e.outputSchema,target:e.name}}),i=resolveAgentStartTarget({action:r,bundle:n,dynamicSelections:t.dynamicSelections,isRootSession:t.parent.rootSessionId===t.parent.sessionId}),a={auth:e.auth,bundle:n,context:t,key:e.key,replyTo:e.replyTo};return i.kind===`remote`?await startRemoteSession({...a,target:i}):await startLocalSession({...a,target:i})}async function sendAgentSessionMessageStep(e){"use step";let{address:t,context:n}=e;if(t.kind===`remote`){let r=await resolveSessionRemote(n,t);await continueRemoteAgentSession({auth:e.auth.current,callback:{callId:n.parent.callId,subagentName:t.name,token:e.replyTo,url:createWorkflowCallbackUrl(t.callbackBaseUrl,createEveCallbackRoutePath(e.replyTo))},message:e.message,outputSchema:e.outputSchema,remote:r,sessionId:t.sessionId});return}if((await commandLocalSession({...e,address:t},{auth:e.auth.current,schedule:n.schedule,caller:{callId:n.parent.callId,replyTo:{kind:`hook`,token:e.replyTo},subagentName:t.name},kind:`send`,payload:{message:e.message,outputSchema:e.outputSchema}}).catch(e=>{throw SessionStrandedError.is(e)?Error(`Agent "${t.name}" can no longer receive messages: ${e.message}`,{cause:e}):e})).status!==`accepted`)throw Error(`Agent "${t.name}" can no longer receive messages; its session ended.`)}async function cancelAgentSessionTurnStep(e){"use step";let{address:t}=e;try{if(t.kind===`remote`){let n=await resolveSessionRemote(e.context,t);await cancelRemoteAgentTurn({remote:n,sessionId:t.sessionId});return}await commandLocalSession({...e,address:t},{kind:`cancel`})}catch(e){logError(log,`failed to cancel an agent session turn`,e,{name:t.name,sessionId:t.sessionId})}}async function endAgentSessionsStep(e){"use step";await Promise.all(e.sessions.map(endAgentSession))}async function endAgentSession(e){let{address:t,context:n}=e;try{if(t.kind===`remote`){let e=await resolveSessionRemote(n,t);await resetRemoteAgentSession({reason:RUN_FINISHED_REASON,remote:e,sessionId:t.sessionId});return}await commandLocalSession({...e,address:t},{kind:`reset`,reason:RUN_FINISHED_REASON})}catch(e){logError(log,`failed to end an agent session`,e,{name:t.name,sessionId:t.sessionId})}}async function commandLocalSession(e,t){let{continuationToken:n,sessionId:r}=e.address,i=await dispatchWorkflowSessionCommand({command:t,sessionId:r});if(i.status===`accepted`||i.status===`reset`)return i;let a=await waitForSessionInbox(r)?r:(await resolveContinuation(n))?.sessionId;return a===void 0?i:await dispatchWorkflowSessionCommand({command:t,sessionId:a})}async function startLocalSession(e){let{auth:t,bundle:n,context:r,target:i}=e,{action:a}=i,{childContinuationToken:o,runInput:s}=buildSubagentRunInput({action:a,auth:t.current,capabilities:r.capabilities,schedule:r.schedule,channelMetadata:r.channelMetadata,continuationKey:e.key,graph:n.graph,inheritedConversation:r.conversation,initiatorAuth:t.initiator,limits:r.limits,parent:createParentContext(r,e.replyTo),sandboxSessionId:r.sandbox.sessionId,selfAgent:i.source.type===`runtime`,session:{continuationToken:e.replyTo,sandboxState:r.sandbox.state,sessionId:r.parent.sessionId},source:i.source}),c=createWorkflowRuntime({compiledArtifactsSource:n.compiledArtifactsSource,dynamicSubagentAgentConfig:i.dynamicSubagentAgentConfig,nodeId:a.nodeId}),l=r.toolStubs;l!==void 0&&(l={...l,agentPath:stubToolPath(l,a.name)});let u=(await contextStorage.run(new ContextContainer({localDevRequest:r.localDevRequest}),()=>c.createSession({...s,toolStubs:l}))).sessionId;return getStepMetadata().attempt>1&&({runId:u}=await waitForCommandHookOwner(sessionInboxHookToken(o))),{continuationToken:o,kind:`local`,name:a.name,nodeId:a.nodeId,sessionId:u}}async function startRemoteSession(e){let{auth:t,bundle:n,context:r,target:i}=e,{action:a}=i,o=resolveRemoteAgentForAction({dynamicRemoteAgent:i.dynamicRemoteAgent,nodeId:a.nodeId,registry:n.subagentRegistry.subagentsByNodeId,remoteAgentName:a.remoteAgentName}),s=resolveWorkflowCallbackBaseUrl(getWorkflowMetadata().url),c=await startRemoteAgentSession({action:a,auth:t.current,callbackBaseUrl:s,capabilities:r.capabilities,initiatorAuth:t.initiator,operationId:`agent-session:${e.key}`,originAudience:r.trace.originAudience,parent:createParentContext(r,e.replyTo),remote:o,session:{continuationToken:e.replyTo}});return{callbackBaseUrl:s,kind:`remote`,forwardPrincipal:o.forwardPrincipal,name:a.remoteAgentName,nodeId:a.nodeId,resolverId:i.dynamicRemoteAgent?.credentialsStepId??a.nodeId,sessionId:c.sessionId,url:o.url}}function createParentContext(e,t){return{continuationToken:t,conversationId:e.trace.conversationId??resolveConversationId(e.parent.rootSessionId),lineage:e.parent,originAudience:e.trace.originAudience,traceContext:e.trace.parentTraceContext,traceRoot:e.traceRoot}}async function resolveSessionRemote(e,t){let n=await loadAgentSessionBundle(e),r=e.dynamicSelections[t.nodeId];return{...resolveRemoteAgentForAction({dynamicRemoteAgent:r?.kind===`remote`?r.remoteAgent:void 0,nodeId:t.nodeId,registry:n.subagentRegistry.subagentsByNodeId,remoteAgentName:t.name}),url:t.url}}async function loadAgentSessionBundle(e){return await getCompiledRuntimeAgentBundle({compiledArtifactsSource:resolveDurableCompiledArtifactsSource(e.bundle.source),nodeId:e.bundle.nodeId})}export{cancelAgentSessionTurnStep,endAgentSessionsStep,openAgentSessionStep,sendAgentSessionMessageStep};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createLogger}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{appliedSession,saveSessionProjection}from"#harness/session-machine/current.js";import{AuthKey,SandboxKey,TurnDeliveryIdsKey}from"#context/keys.js";import{createDurableSessionValues}from"#execution/durable-session-store.js";import{preserveSerializedSessionDynamicModelSelection}from"#context/serialized-dynamic-model-selection.js";import{withContextScope}from"#context/run-step.js";import{serializeContext}from"#context/serialize.js";import{preserveCancelledTurnMessage}from"#execution/cancelled-turn-message.js";import{takeDeferredMessage}from"#harness/hitl/index.js";import{preserveSerializedInstrumentationState}from"#instrumentation/state.js";import{preserveSerializedAgentTraceState}from"#tracing/agent-trace-context-store.js";const log=createLogger(`execution.cancelled-turn`);async function cancelledWithoutCheckpoint(e,t,n){let r=appliedSession(e),i=r??t,a=n;if(r!==void 0){let e=takeDeferredMessage(r);i=e.session,e.message!==void 0&&(a={...n,message:e.message})}if(e.get(SandboxKey)===void 0&&hasFileParts(a?.message))try{return(await withContextScope(e,i,async e=>({result:void 0,session:await preserveCancelledTurnMessage(e,a)}))).session}catch(t){log.warn(`staging a cancelled turn's attachments failed`,{error:t}),e.clearVirtualContext()}return await contextStorage.run(e,()=>preserveCancelledTurnMessage(i,a))}function hasFileParts(e){return Array.isArray(e)&&e.some(e=>e.type===`file`)}async function createCancelledModelCallBatchResult(e){let t=serializeContext(e.ctx),n=e.checkpoint?.result.session??await cancelledWithoutCheckpoint(e.ctx,e.initialSession,e.stepInput),r={...e.checkpoint?.serializedContext??e.beforeBatchContext,[AuthKey.name]:t[AuthKey.name],[TurnDeliveryIdsKey.name]:t[TurnDeliveryIdsKey.name]};return{action:`cancelled`,serializedContext:preserveSerializedInstrumentationState(preserveSerializedAgentTraceState(preserveSerializedSessionDynamicModelSelection(r,t),t),t),...createDurableSessionValues(saveSessionProjection(n,e.ctx))}}export{createCancelledModelCallBatchResult};
|
|
1
|
+
import{createLogger}from"#internal/logging.js";import{contextStorage}from"#context/container.js";import{appliedSession,saveSessionProjection}from"#harness/session-machine/current.js";import{AuthKey,OfferedCatalogToolsKey,SandboxKey,TurnDeliveryIdsKey}from"#context/keys.js";import{createDurableSessionValues}from"#execution/durable-session-store.js";import{preserveSerializedSessionDynamicModelSelection}from"#context/serialized-dynamic-model-selection.js";import{withContextScope}from"#context/run-step.js";import{serializeContext}from"#context/serialize.js";import{preserveCancelledTurnMessage}from"#execution/cancelled-turn-message.js";import{takeDeferredMessage}from"#harness/hitl/index.js";import{preserveSerializedInstrumentationState}from"#instrumentation/state.js";import{preserveSerializedAgentTraceState}from"#tracing/agent-trace-context-store.js";const log=createLogger(`execution.cancelled-turn`);async function cancelledWithoutCheckpoint(e,t,n){let r=appliedSession(e),i=r??t,a=n;if(r!==void 0){let e=takeDeferredMessage(r);i=e.session,e.message!==void 0&&(a={...n,message:e.message})}if(e.get(SandboxKey)===void 0&&hasFileParts(a?.message))try{return(await withContextScope(e,i,async e=>({result:void 0,session:await preserveCancelledTurnMessage(e,a)}))).session}catch(t){log.warn(`staging a cancelled turn's attachments failed`,{error:t}),e.clearVirtualContext()}return await contextStorage.run(e,()=>preserveCancelledTurnMessage(i,a))}function hasFileParts(e){return Array.isArray(e)&&e.some(e=>e.type===`file`)}async function createCancelledModelCallBatchResult(e){let t=serializeContext(e.ctx),n=e.checkpoint?.result.session??await cancelledWithoutCheckpoint(e.ctx,e.initialSession,e.stepInput),r={...e.checkpoint?.serializedContext??e.beforeBatchContext,[AuthKey.name]:t[AuthKey.name],[OfferedCatalogToolsKey.name]:t[OfferedCatalogToolsKey.name],[TurnDeliveryIdsKey.name]:t[TurnDeliveryIdsKey.name]};return{action:`cancelled`,serializedContext:preserveSerializedInstrumentationState(preserveSerializedAgentTraceState(preserveSerializedSessionDynamicModelSelection(r,t),t),t),...createDurableSessionValues(saveSessionProjection(n,e.ctx))}}export{createCancelledModelCallBatchResult};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{completeConnectionSignIn,listConnectionTools,listingFailureMessage}from"./connection-auth.js";import{closestNames,isEmptyQuery,rankCandidates}from"./rank.js";import{connectionToolSignature,entrySignature}from"./signatures.js";import{connectionSignInEntry}from"./connection-entry.js";import{CALL_TOOL_NAME,SEARCH_TOOL_NAME,SKILL_TOOL_NAME}from"#protocol/catalog-tools.js";import{serializeInputSchema,toInputSchema}from"#tools/schema.js";import{connectionToolName}from"#connections/ownership.js";function searchDescription({connections:e,skills:t,tools:n}){return[`
|
|
1
|
+
import{completeConnectionSignIn,listConnectionTools,listingFailureMessage}from"./connection-auth.js";import{closestNames,isEmptyQuery,rankCandidates}from"./rank.js";import{connectionToolSignature,entrySignature}from"./signatures.js";import{connectionSignInEntry}from"./connection-entry.js";import{CALL_TOOL_NAME,SEARCH_TOOL_NAME,SKILL_TOOL_NAME}from"#protocol/catalog-tools.js";import{serializeInputSchema,toInputSchema}from"#tools/schema.js";import{connectionToolName}from"#connections/ownership.js";function searchDescription({connections:e,skills:t,tools:n}){return[`Search your own catalog for tools, agents, skills, and connected services that aren't in your tool list. Use it when nothing in your tool list fits the request; it doesn't search the web.`,n?`A result with \`tool\` has the exact name, description, and TypeScript signature: call it with ${CALL_TOOL_NAME}({ name, input }).`:void 0,t?`A result with \`skill\` has the name and description: load it with ${SKILL_TOOL_NAME}({ name }).`:void 0,"`searched` counts the entries the query covered, and `remaining` counts the matches past `limit`: when `remaining` is 0, nothing else the query covered matched. Connections under `unavailable` weren't searched.",`When you already know a name or connection, from the catalog listing, an earlier result, or an error, search it directly: the exact name, or "<connection>__", which is faster and returns only that connection's tools.`,e?`A connection that needs sign-in appears as a tool named after the connection: calling it with ${CALL_TOOL_NAME}({ name }) asks the user to sign in. \`searched\` counts its tools only after sign-in.`:void 0].filter(e=>e!==void 0).join(` `)}const SEARCH_INPUT_SCHEMA=toInputSchema({type:`object`,properties:{query:{type:`string`,minLength:1,description:`Words describing the capability, such as 'list open issues'; an exact name; or a namespace prefix such as 'linear__', which searches only that connection's tools.`},limit:{type:`integer`,minimum:1,maximum:50,description:`Maximum results, best matches first. Defaults to 10.`}},required:[`query`],additionalProperties:!1}),SEARCH_LABEL={start:e=>`Search tools${labelQuery(e)}`,complete:(e,t)=>{let{results:n,unavailable:r=[]}=t,i=`Searched tools${labelQuery(e)}, found ${n.length===0?`nothing`:String(n.length)}`;if(n.length>0||r.length===0)return i;let a=r.length===1?`connection`:`connections`;return`${i}; ${String(r.length)} ${a} unavailable`}};function labelQuery(e){let t=e.query?.trim();return t?` for “${t}”`:``}function createSearchTool(e){return{description:searchDescription(e.reach),execute:t=>search(e,t),frameworkTool:!0,inputSchema:SEARCH_INPUT_SCHEMA,label:SEARCH_LABEL,name:SEARCH_TOOL_NAME}}async function search(e,t){let n=t.query??``;if(isEmptyQuery(n))throw Error(`${SEARCH_TOOL_NAME} needs at least one word in query, such as a capability ("list open issues") or a name or connection prefix ("linear__").`);let r=parseNamespace(n),inScope=e=>r===void 0||inNamespace(e,r),i=[...e.deferred.map(t=>entryCandidate(t,e.describe)),...e.skills.map(skillCandidate)].filter(e=>inScope(e.fullName)),a=[],{registry:o}=e;if(o!==void 0){let e=o.getConnections().filter(({connectionName:e})=>r===void 0||mayOwnNamespace(e,r)),t=await Promise.all(e.map(e=>searchConnection(o,e)));for(let e of t)`unavailable`in e?a.push(e.unavailable):i.push(...e.candidates.filter(e=>inScope(e.fullName)))}if(r!==void 0&&i.length===0&&a.length===0)throw Error(unknownNamespaceMessage(r,o?.getConnections()??[]));let s=clampInteger(t.limit,1,50,10),c=rankCandidates(n,i),l=c.slice(0,s).map(e=>e.result()),u={results:l,remaining:c.length-l.length,searched:i.length};return a.length>0?{...u,unavailable:a}:u}function parseNamespace(e){let t=(e.trim().split(/\s+/u)[0]??``).replace(/^[^A-Za-z0-9_-]+/u,``),n=t.slice(0,Math.max(0,t.lastIndexOf(`__`))).replace(/_+$/u,``);return n===``?void 0:n}function inNamespace(e,t){return e===t||e.startsWith(`${t}__`)}function mayOwnNamespace(e,t){return inNamespace(e,t)||t.startsWith(`${e}__`)}function unknownNamespaceMessage(e,t){if(t.some(({connectionName:t})=>t===e))return`Connection "${e}" has no tools.`;let n=closestNames(e,t.map(({connectionName:e,description:t})=>({description:t,name:e})));return`No entries are named "${e}__…". ${n.length>0?`Closest connections: ${n.join(`, `)}.`:`Find names in the catalog listing or your tool list, or call ${SEARCH_TOOL_NAME} with plain words.`}`}async function searchConnection(e,t){let n=t.connectionName,r;try{r=await listConnectionTools(t,await completeConnectionSignIn(e,t))}catch(e){return{unavailable:{connection:n,error:listingFailureMessage(n,e)}}}return`failure`in r?{unavailable:{connection:n,error:r.failure}}:`authorization`in r?{candidates:[signInCandidate(e,t)]}:{candidates:r.tools.map(e=>toolCandidate(t,e))}}function entryCandidate(e,t){let n=serializeInputSchema(e.inputSchema),r=t(e);return{description:r,inputSchema:n,name:e.name,result:()=>({description:r,signature:entrySignature(e,n),tool:e.name}),fullName:e.name}}function skillCandidate({description:e,name:t,path:n}){return{description:e,fullName:t,name:t,result:()=>({description:e,path:n,skill:t})}}function toolCandidate(e,t){let n=connectionToolName(e.connectionName,t.name);return{connection:{description:e.description,name:e.connectionName},description:t.description,inputSchema:t.inputSchema,name:t.name,result:()=>({description:t.description,signature:connectionToolSignature(e,t),tool:n}),fullName:n}}function signInCandidate(e,t){let n=connectionSignInEntry(e,t);return{description:t.description,name:t.connectionName,result:()=>({description:n.description,signature:entrySignature(n),tool:n.name}),fullName:n.name}}function clampInteger(e,t,n,r){return typeof e!=`number`||!Number.isFinite(e)?r:Math.min(n,Math.max(t,Math.trunc(e)))}export{createSearchTool};
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The step's catalog: one table of every entry a model step can reach. Direct
|
|
3
|
-
* entries go into the model's tool list next to the catalog tools the
|
|
3
|
+
* entries go into the model's tool list next to the catalog tools the session
|
|
4
4
|
* has: `eve__search` finds entries, `eve__tool` calls deferred entries and
|
|
5
5
|
* connection tools, and `eve__skill` loads skills. A call resolves to its entry
|
|
6
6
|
* here and then runs exactly as a direct call would, so only model history
|
|
7
7
|
* ever names a catalog tool.
|
|
8
8
|
*/
|
|
9
|
-
import type { ContextReader } from "#context/key.js";
|
|
9
|
+
import type { ContextAccessor, ContextReader } from "#context/key.js";
|
|
10
|
+
import { type OfferedCatalogTools } from "#context/keys.js";
|
|
10
11
|
import type { HarnessToolDefinition } from "#harness/execute-tool.js";
|
|
11
12
|
import type { CallResolver, HarnessSession, HarnessToolLookup, HarnessToolMap } from "#harness/types.js";
|
|
12
13
|
import type { ResolvedConnectionDefinition } from "#runtime/types.js";
|
|
13
14
|
import { type CatalogSkill } from "./skills.js";
|
|
14
15
|
export interface StepCatalog extends HarnessToolLookup {
|
|
15
|
-
/** The model's tool list: direct entries, then the catalog tools the
|
|
16
|
+
/** The model's tool list: direct entries, then the catalog tools the session has. */
|
|
16
17
|
readonly advertised: HarnessToolMap;
|
|
17
18
|
readonly connections: readonly ResolvedConnectionDefinition[];
|
|
18
19
|
/** Entries reached only through `eve__tool`, connection tools aside. */
|
|
@@ -21,6 +22,8 @@ export interface StepCatalog extends HarnessToolLookup {
|
|
|
21
22
|
readonly entries: HarnessToolMap;
|
|
22
23
|
/** Every skill the session can load, deferred or not. */
|
|
23
24
|
readonly skills: ReadonlyMap<string, CatalogSkill>;
|
|
25
|
+
/** The catalog tools the tool list offers; see {@link recordOfferedCatalogTools}. */
|
|
26
|
+
readonly offered: OfferedCatalogTools;
|
|
24
27
|
/**
|
|
25
28
|
* Whether the session offers tasks: one of the agent's own tools it sees
|
|
26
29
|
* starts them, or the agent resolves subagents at runtime. Both are fixed by
|
|
@@ -49,3 +52,9 @@ export declare function buildStepCatalog(input: {
|
|
|
49
52
|
readonly endsTurn: boolean;
|
|
50
53
|
readonly session: Pick<HarnessSession, "rootSessionId">;
|
|
51
54
|
}): StepCatalog;
|
|
55
|
+
/**
|
|
56
|
+
* Keeps the catalog tools `catalog` offers for every later step of the
|
|
57
|
+
* session. The step that calls the model records them; a step rebuilt to
|
|
58
|
+
* resume a parked call only reads them.
|
|
59
|
+
*/
|
|
60
|
+
export declare function recordOfferedCatalogTools(ctx: ContextAccessor | undefined, { offered }: StepCatalog): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{closestNames}from"./rank.js";import{entrySignature}from"./signatures.js";import{connectionEntry,connectionSignInEntry}from"./connection-entry.js";import{createSearchTool}from"./search.js";import{createSkillLoader,sessionSkills,unknownSkillMessage}from"./skills.js";import{isObject}from"#shared/guards.js";import{CALL_TOOL_NAME,SEARCH_TOOL_NAME,SKILL_ENTRY_NAME,SKILL_TOOL_NAME}from"#protocol/catalog-tools.js";import{refineJsonSchema}from"#tools/schema.js";import{connectionToolName}from"#connections/ownership.js";import{eveNamespaceReservation}from"#protocol/runtime-tools.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{ConnectionRegistryKey}from"#context/providers/connection-key.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{startsTasks}from"#execution/tasks/tool-entry-point.js";import{buildDynamicSubagentTools}from"#context/dynamic-subagent-lifecycle.js";import{withTaskTools}from"#execution/tasks/model-step.js";import{runEntryCall}from"#harness/execute-call.js";import{checkToolCallInput}from"#harness/tool-call-io.js";const CALL_TOOL_DESCRIPTION=`Call a tool that isn't in your tool list by its exact name from ${SEARCH_TOOL_NAME}, with \`input\` matching its signature.`,SEARCHABLE_SKILL_DESCRIPTION=`Load a skill's instructions when the request clearly matches a listed skill or one ${SEARCH_TOOL_NAME} found, or the user asks for it, then follow them.`;function catalogToolsFor(e
|
|
1
|
+
import{closestNames}from"./rank.js";import{entrySignature}from"./signatures.js";import{connectionEntry,connectionSignInEntry}from"./connection-entry.js";import{createSearchTool}from"./search.js";import{createSkillLoader,sessionSkills,unknownSkillMessage}from"./skills.js";import{isObject}from"#shared/guards.js";import{OfferedCatalogToolsKey}from"#context/keys.js";import{CALL_TOOL_NAME,SEARCH_TOOL_NAME,SKILL_ENTRY_NAME,SKILL_TOOL_NAME}from"#protocol/catalog-tools.js";import{refineJsonSchema}from"#tools/schema.js";import{connectionToolName}from"#connections/ownership.js";import{eveNamespaceReservation}from"#protocol/runtime-tools.js";import{buildDynamicTools}from"#context/build-dynamic-tools.js";import{ConnectionRegistryKey}from"#context/providers/connection-key.js";import{BundleKey}from"#runtime/sessions/runtime-context-keys.js";import{startsTasks}from"#execution/tasks/tool-entry-point.js";import{buildDynamicSubagentTools}from"#context/dynamic-subagent-lifecycle.js";import{withTaskTools}from"#execution/tasks/model-step.js";import{runEntryCall}from"#harness/execute-call.js";import{checkToolCallInput}from"#harness/tool-call-io.js";const CALL_TOOL_DESCRIPTION=`Call a tool that isn't in your tool list by its exact name from ${SEARCH_TOOL_NAME}, with \`input\` matching its signature.`,SEARCHABLE_SKILL_DESCRIPTION=`Load a skill's instructions when the request clearly matches a listed skill or one ${SEARCH_TOOL_NAME} found, or the user asks for it, then follow them.`;function catalogToolsFor(e){let{offered:t}=e,n=[...e.skills.values()],r=t?.connections===!0||e.connections.length>0,i=t?.searchableSkills===!0||n.some(e=>e.deferred),a=t?.tools===!0||r||e.deferred.size>0;return{connections:r,search:a||i,searchableSkills:i,skills:t?.skills===!0||n.length>0,tools:a}}function buildStepCatalog(e){let visible=t=>isVisible(t,e.session),t=((e.ctx?.get(BundleKey))?.subagentRegistry.dynamicResolvers.length??0)>0||[...e.agentTools.values()].some(e=>visible(e)&&startsTasks(e)),n=stepEntries(e,visible),r=t?withTaskTools(n):n,i=new Map,a=new Map;for(let[e,t]of r)(t.deferred===!0?a:i).set(e,t);let o=e.ctx?.get(ConnectionRegistryKey),s=o?.getConnections()??[],c=sessionSkills(e.ctx),l=catalogToolsFor({connections:s,deferred:a,offered:e.ctx?.get(OfferedCatalogToolsKey),skills:c}),{search:u,...d}=l,f=createSkillLoader(c),p=new Map(i),toolEntry=e=>r.get(e)??p.get(e)??(o===void 0?void 0:connectionEntryNamed(e,o,s)),describe=t=>describeEntry(t,e.endsTurn),m={advertised:p,connections:s,deferred:a,describe,entries:r,get:e=>e===SKILL_ENTRY_NAME?f:toolEntry(e),offered:d,offersTasks:t,resolve:e=>{if(e.toolName===CALL_TOOL_NAME&&l.tools){let t=targetName(e.input),n=t===void 0?void 0:toolEntry(t);return t===void 0||n===void 0||!callableByName(n)?void 0:{call:asEntryCall(e,t),definition:n}}if(e.toolName===SKILL_TOOL_NAME&&l.skills){let t=targetName(e.input);return t===void 0||!c.has(t)?void 0:{call:{...e,input:{name:t},toolName:SKILL_ENTRY_NAME},definition:f}}let t=p.get(e.toolName);return t===void 0?void 0:{call:e,definition:t}},skills:c};if(l.search){let e=createSearchTool({deferred:[...a.values()],describe,reach:{connections:l.connections,skills:l.searchableSkills,tools:l.tools},registry:o,skills:[...c.values()].filter(e=>e.deferred)});p.set(e.name,e)}return l.tools&&p.set(CALL_TOOL_NAME,createCallTool(m,toolEntry,l)),l.skills&&p.set(SKILL_TOOL_NAME,createSkillTool(m,toolEntry,l)),m}function recordOfferedCatalogTools(e,{offered:t}){Object.values(t).includes(!0)&&e?.set(OfferedCatalogToolsKey,t)}function targetName(e){return isObject(e)&&typeof e.name==`string`?e.name:void 0}function asEntryCall(e,t){let n=e.input.input;return{...e,input:n??{},toolName:t}}function describeEntry(e,t){return t&&e.endsTurn===!0?`${e.description}\n\nCalling this tool ends your turn once it succeeds: do not write a reply or call other tools in the same step. If it fails, you will see the error and can continue.`.trimStart():e.description}function stepEntries(e,t){let n=new Map([...e.agentTools].filter(([,e])=>t(e)));if(e.ctx===void 0)return n;for(let r of buildDynamicSubagentTools(e.ctx).filter(t))n.set(r.name,r);let r=new Set;for(let i of buildDynamicTools(e.ctx).filter(t))r.has(i.name)||(r.add(i.name),n.set(i.name,i));return n}function isVisible(e,t){return e.rootOnly!==!0&&e.availableInSubagents!==!1&&e.behavior?.availability.includes(`root-session`)!==!0||t.rootSessionId===void 0}function connectionEntryNamed(e,t,n){for(let r of n){if(e===r.connectionName)return connectionSignInEntry(t,r);let n=connectionToolName(r.connectionName,``);if(e.length>n.length&&e.startsWith(n))return connectionEntry(t,r,e.slice(n.length))}}function createCallTool(e,t,n){return{description:n.connections?`${CALL_TOOL_DESCRIPTION} Prefer connected services over web search or general knowledge when a request relates to them.`:CALL_TOOL_DESCRIPTION,execute:(t,n)=>runResolved(e,{input:t,toolName:CALL_TOOL_NAME},n),frameworkTool:!0,inputSchema:refineJsonSchema({type:`object`,properties:{name:{type:`string`,description:`The tool's exact name, as ${SEARCH_TOOL_NAME} returns it.`},input:{type:`object`,description:`Arguments matching the tool's signature. Defaults to {}.`}},required:[`name`],additionalProperties:!1},n=>resolveToolInput(e,t,n)),name:CALL_TOOL_NAME}}function createSkillTool(e,t,n){return{description:n.searchableSkills?SEARCHABLE_SKILL_DESCRIPTION:`Load a skill's instructions when the request clearly matches one of your listed skills or the user asks for it, then follow them.`,execute:(t,n)=>runResolved(e,{input:t,toolName:SKILL_TOOL_NAME},n),frameworkTool:!0,inputSchema:refineJsonSchema({type:`object`,properties:{name:{type:`string`,description:n.searchableSkills?`The skill's name, from your listed skills or ${SEARCH_TOOL_NAME}.`:`The skill's name, from your listed skills.`}},required:[`name`],additionalProperties:!1},async r=>resolveSkillInput(e,t,r.name,n)),name:SKILL_TOOL_NAME}}function runResolved(e,t,n){let r=e.resolve(t);if(r===void 0)throw Error(`A ${t.toolName} call ran without a resolved entry.`);return runEntryCall(r,n)}function callableByName(e){return e.deferred===!0||eveNamespaceReservation(e.name)===void 0&&(e.execute!==void 0||e.workflowId!==void 0)}async function resolveToolInput(e,t,{input:n,name:r}){let i=t(r);if(i===void 0)return failure(`name`,unknownEntryMessage(r,e));if(!callableByName(i))return failure(`name`,`"${r}" is in your tool list; call it directly.`);let a=await checkToolCallInput(i,n,``);if(a.kind===`threw`)throw a.error;return a.kind===`invalid`?{issues:(isConnectionTool(r,e.connections)?a.issues:[...a.issues,{message:`Signature: ${entrySignature(i)}`}]).map(({message:e,path:t=[]})=>({message:e,path:[`input`,...t]}))}:{value:{input:a.value,name:r}}}function resolveSkillInput(e,t,n,r){if(e.skills.has(n))return{value:{name:n}};let i=e.connections.map(e=>e.connectionName),a=i.includes(n)?void 0:t(n);return a===void 0?failure(`name`,unknownSkillMessage(n,e.skills,i,r.searchableSkills)):failure(`name`,a.deferred===!0?`"${n}" is a tool, not a skill; call it with ${CALL_TOOL_NAME}({ name: "${n}" }).`:`"${n}" is a tool in your tool list, not a skill; call it directly.`)}function isConnectionTool(e,t){return t.some(({connectionName:t})=>e.startsWith(connectionToolName(t,``)))}function failure(e,t){return{issues:[{message:t,path:[e]}]}}function unknownEntryMessage(e,t){if(t.skills.has(e))return`"${e}" is a skill; load it with ${SKILL_TOOL_NAME}({ name: "${e}" }).`;let n=[...t.deferred.values()].map(({description:e,name:t})=>({description:e,name:t})),r=closestNames(e,n);return`No tool named "${e}".${r.length>0?` Closest tools: ${r.join(`, `)}.`:` Find tools with ${SEARCH_TOOL_NAME}.`}`}export{buildStepCatalog,recordOfferedCatalogTools};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
/** Shared owner-side dispatch context preparation. */
|
|
2
2
|
import { type ChannelAdapter, type ChannelAdapterContext } from "#channel/adapter.js";
|
|
3
3
|
import { type LocalDevRequestProvenance } from "#context/keys.js";
|
|
4
4
|
import { ContextContainer } from "#context/container.js";
|
|
@@ -61,7 +61,6 @@ export declare function prepareCoordinationDispatch(input: {
|
|
|
61
61
|
readonly sessionState: DurableSessionState;
|
|
62
62
|
}): Promise<PreparedCoordinationDispatch | undefined>;
|
|
63
63
|
interface DispatchBatch {
|
|
64
|
-
readonly approvers?: Readonly<Record<string, SessionAuthContext>>;
|
|
65
64
|
readonly event: {
|
|
66
65
|
readonly sequence: number;
|
|
67
66
|
readonly stepIndex: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ConversationContextKey}from"#shared/conversation-context.js";import"#channel/adapter.js";import"#context/container.js";import{AuthKey,CapabilitiesKey,ChannelInstrumentationKey,InitiatorAuthKey,LocalDevRequestKey,ParentSessionKey,TraceRootKey}from"#context/keys.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{activeTurnId,runtimeWait,storedProjection,turnPosition}from"#harness/session-machine/view.js";import"#subagents/tool.js";import{readDurableSession}from"#execution/durable-session-store.js";import{deserializeContext}from"#context/serialize.js";import{readDynamicSubagentSelections}from"#context/dynamic-subagent-lifecycle.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{assertUniqueCoordinationCallIds}from"#harness/coordination.js";import{resolveTraceRootSessionId}from"#shared/trace-root.js";import{hydrateDurableSession}from"#execution/session.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{resolveWorkflowAgentMetadata}from"#execution/agent-sessions/metadata.js";async function prepareCoordinationDispatch(e){let t=readDurableSession(e.sessionState),n=runtimeWait(t.state);if(n===void 0)return;let r=n.tasks;if(r.length===0)return;let i=n.event.turnId||activeTurnId(turnPosition(storedProjection(t.state))),a=await deserializeContext(e.serializedContext);return{...await prepareActionDispatch({batch:{
|
|
1
|
+
import{ConversationContextKey}from"#shared/conversation-context.js";import"#channel/adapter.js";import"#context/container.js";import{AuthKey,CapabilitiesKey,ChannelInstrumentationKey,InitiatorAuthKey,LocalDevRequestKey,ParentSessionKey,TraceRootKey}from"#context/keys.js";import{BundleKey,ChannelKey}from"#runtime/sessions/runtime-context-keys.js";import{activeTurnId,runtimeWait,storedProjection,turnPosition}from"#harness/session-machine/view.js";import"#subagents/tool.js";import{readDurableSession}from"#execution/durable-session-store.js";import{deserializeContext}from"#context/serialize.js";import{readDynamicSubagentSelections}from"#context/dynamic-subagent-lifecycle.js";import{buildAdapterContext}from"#channel/adapter-context.js";import{assertUniqueCoordinationCallIds}from"#harness/coordination.js";import{resolveTraceRootSessionId}from"#shared/trace-root.js";import{hydrateDurableSession}from"#execution/session.js";import{resolveEffectiveAgentRuntime}from"#execution/effective-agent-config.js";import{resolveWorkflowAgentMetadata}from"#execution/agent-sessions/metadata.js";async function prepareCoordinationDispatch(e){let t=readDurableSession(e.sessionState),n=runtimeWait(t.state);if(n===void 0)return;let r=n.tasks;if(r.length===0)return;let i=n.event.turnId||activeTurnId(turnPosition(storedProjection(t.state))),a=await deserializeContext(e.serializedContext);return{...await prepareActionDispatch({batch:{event:{...n.event,turnId:i},requests:r},ctx:a,durableSession:t,plan:()=>r,serializedContext:e.serializedContext}),sessionState:e.sessionState}}async function prepareActionDispatch(e){let{batch:t,durableSession:n}=e;assertUniqueCoordinationCallIds(t.requests);let r=e.ctx,i=r.require(BundleKey),a=resolveEffectiveAgentRuntime(i,r),o=hydrateDurableSession({compactionOverrides:{thresholdPercent:a.thresholdPercent},durable:n,turnAgent:a.turnAgent}),s=r.require(ChannelKey),c=e.plan({bundle:i,ctx:r,requests:t.requests,session:o}),l=resolveActiveSandboxSessionId(s.state,o.sessionId);return{adapter:s,adapterCtx:buildAdapterContext(s,r),auth:r.get(AuthKey)??null,batch:t,bundle:i,capabilities:r.get(CapabilitiesKey),channelMetadata:r.get(ChannelInstrumentationKey),dynamicSubagentSelections:readDynamicSubagentSelections(r),inheritedConversation:r.get(ConversationContextKey),initiatorAuth:r.get(InitiatorAuthKey)??null,localDevRequest:r.get(LocalDevRequestKey),parentSession:r.get(ParentSessionKey),plan:c,sandboxSessionId:l,serializedContext:e.serializedContext,session:o,traceRoot:childTraceRoot(r,o.sessionId),workflowAgents:resolveWorkflowAgentMetadata(r)}}function childTraceRoot(e,t){if(e.get(TraceRootKey)!==void 0)return{kind:`inherited`,sessionId:resolveTraceRootSessionId(e,t)}}function resolveActiveSandboxSessionId(e,t){if(typeof e!=`object`||!e)return t;let n=e.sandboxSessionId;return typeof n==`string`&&n.length>0?n:t}export{prepareActionDispatch,prepareCoordinationDispatch};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{storedProjection}from"#harness/session-machine/view.js";import{createDurableSessionState}from"#execution/durable-session-store.js";import{prepareCoordinationDispatch}from"#execution/coordination-dispatch-shared.js";import{publishSessionEvents}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/state-delta.js";import{startWorkflowTask}from"#execution/tools/workflow/start.js";import{sendToTask,startTaskRun}from"#execution/tasks/start.js";import{captureAgentSessionContext,resolveStepAgentLimits}from"#execution/agent-sessions/context.js";import{sessionView}from"#harness/session-machine/commit.js";import{startTask}from"#harness/session-machine/transitions.js";async function dispatchCoordinationStep(e){"use step";return await withSessionStateDelta(e,dispatchCoordination)}async function dispatchCoordination(e){let t=await prepareCoordinationDispatch({serializedContext:e.serializedContext,sessionState:e.sessionState});if(t===void 0)return{results:[],serializedContext:e.serializedContext,sessionState:e.sessionState};let{batch:n,session:r}=t,i=r,a=[],o=[],s=resolveStepAgentLimits(t)
|
|
1
|
+
import{storedProjection}from"#harness/session-machine/view.js";import{readTaskTable}from"#execution/tasks/table.js";import{createDurableSessionState}from"#execution/durable-session-store.js";import{prepareCoordinationDispatch}from"#execution/coordination-dispatch-shared.js";import{publishSessionEvents}from"#execution/publish-session-events.js";import{withSessionStateDelta}from"#execution/session/state-delta.js";import{startWorkflowTask,startWorkflowToolCallRun}from"#execution/tools/workflow/start.js";import{runEntryToStart,sendToTask,startTaskRun,startsEveryRun}from"#execution/tasks/start.js";import{captureAgentSessionContext,resolveStepAgentLimits}from"#execution/agent-sessions/context.js";import{sessionView}from"#harness/session-machine/commit.js";import{startTask}from"#harness/session-machine/transitions.js";async function dispatchCoordinationStep(e){"use step";return await withSessionStateDelta(e,dispatchCoordination)}async function dispatchCoordination(e){let t=await prepareCoordinationDispatch({serializedContext:e.serializedContext,sessionState:e.sessionState});if(t===void 0)return{results:[],serializedContext:e.serializedContext,sessionState:e.sessionState};let{batch:n,session:r}=t,i=r,a=[],o=[],s=resolveStepAgentLimits(t),c=withPrestartedRuns(t.plan.map(i=>({agentContext:captureAgentSessionContext(t,i.callId,s),auth:{current:t.auth,initiator:t.initiatorAuth},batchEvent:n.event,owner:e.workflowToolRunOwner,parentSession:t.parentSession,session:r,task:i})),readTaskTable(r.state));for(let e of c){let t=await dispatchWorkflowCall({...e,session:i});i=t.session,t.result!==void 0&&a.push(t.result),t.started!==void 0&&o.push(t.started)}return{results:a,...await publishSessionEvents({serializedContext:e.serializedContext,sessionState:i===r?t.sessionState:createDurableSessionState({session:i}),sessionWritable:e.sessionWritable},o.flatMap(e=>startTask(sessionView(storedProjection(i.state),i.state),e).events))}}function withPrestartedRuns(e,t){let n=e.map(e=>e.task),r=n.map(e=>runEntryToStart(t,e));return r.filter(e=>e!==void 0).length>1&&startsEveryRun(t,n)?e.map((e,t)=>{let n=r[t];if(n===void 0)return e;let i=startWorkflowToolCallRun(e,n);return i.catch(()=>{}),{...e,prestarted:{entry:n,run:i}}}):e}async function dispatchWorkflowCall(e){let{entry:t}=e.task;switch(t.entryPoint){case`execute`:return await startWorkflowTask(e);case`task`:case`serve`:return await startTaskRun({...e,entry:t});case`receive`:return await sendToTask({...e,taskId:t.taskId})}}export{dispatchCoordinationStep};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.
|
|
1
|
+
import{runJsProgram}from"#execution/dynamic-workflow/workflow.js";async function runWorkflowProgramTask(e,t){"use workflow";return runJsProgram(e.js,t,{maxSubagents:e.maxSubagents??0})}runWorkflowProgramTask.workflowId=`workflow//eve@0.78.0//runWorkflowProgramTask`;export{runWorkflowProgramTask};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{withDevelopmentSandboxTags}from"#execution/sandbox/development-run.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{buildDockerBaseSetupScript}from"#execution/sandbox/bindings/docker-base-setup.js";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";const DOCKER_SANDBOX_LABEL=`eve.sandbox`,DOCKER_KEEPALIVE_ARGS=[`-c`,`sleep 2147483647`];async function startDockerContainer(e){let t=[`run`,`-d`,`--name`,e.containerName,`--label`,`${DOCKER_SANDBOX_LABEL}=1`,`--label`,`${DOCKER_SANDBOX_LABEL}.role=${e.role}`];for(let[n,r]of Object.entries(withDevelopmentSandboxTags(e.tags)??{}))t.push(`--label`,`${DOCKER_SANDBOX_LABEL}.tag.${n}=${r}`);for(let[n,r]of Object.entries(e.options.env))t.push(`-e`,`${n}=${r}`);e.initialNetworkPolicy===`deny-all`&&t.push(`--network`,`none`),e.resourcesPath!==void 0&&t.push(`--mount`,`type=bind,src=${e.resourcesPath},dst=/eve/resources,readonly`),t.push(`--workdir`,WORKSPACE_ROOT,`--entrypoint`,`/bin/sh`,e.image,...DOCKER_KEEPALIVE_ARGS),expectDockerSuccess(await e.cli.run(t),`start sandbox container "${e.containerName}" from "${e.image}"`)}async function runDockerBaseSetup(e,t){expectDockerSuccess(await e.run([`exec`,`--user`,`root`,t,`/bin/sh`,`-c`,buildDockerBaseSetupScript()]),`prepare base runtime in sandbox container "${t}"`)}async function stopDockerContainerIfRunning(e,t){await e.run([`stop`,`-t`,`0`,t]).catch(()=>{})}export{DOCKER_SANDBOX_LABEL,runDockerBaseSetup,startDockerContainer,stopDockerContainerIfRunning};
|
|
1
|
+
import{withDevelopmentSandboxTags}from"#execution/sandbox/development-run.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{buildDockerBaseSetupScript}from"#execution/sandbox/bindings/docker-base-setup.js";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";import{SANDBOX_AGENT_ENV}from"#execution/sandbox/session.js";const DOCKER_SANDBOX_LABEL=`eve.sandbox`,DOCKER_KEEPALIVE_ARGS=[`-c`,`sleep 2147483647`];async function startDockerContainer(e){let t=[`run`,`-d`,`--name`,e.containerName,`--label`,`${DOCKER_SANDBOX_LABEL}=1`,`--label`,`${DOCKER_SANDBOX_LABEL}.role=${e.role}`];for(let[n,r]of Object.entries(withDevelopmentSandboxTags(e.tags)??{}))t.push(`--label`,`${DOCKER_SANDBOX_LABEL}.tag.${n}=${r}`);for(let[n,r]of Object.entries({...SANDBOX_AGENT_ENV,...e.options.env}))t.push(`-e`,`${n}=${r}`);e.initialNetworkPolicy===`deny-all`&&t.push(`--network`,`none`),e.resourcesPath!==void 0&&t.push(`--mount`,`type=bind,src=${e.resourcesPath},dst=/eve/resources,readonly`),t.push(`--workdir`,WORKSPACE_ROOT,`--entrypoint`,`/bin/sh`,e.image,...DOCKER_KEEPALIVE_ARGS),expectDockerSuccess(await e.cli.run(t),`start sandbox container "${e.containerName}" from "${e.image}"`)}async function runDockerBaseSetup(e,t){expectDockerSuccess(await e.run([`exec`,`--user`,`root`,t,`/bin/sh`,`-c`,buildDockerBaseSetupScript()]),`prepare base runtime in sandbox container "${t}"`)}async function stopDockerContainerIfRunning(e,t){await e.run([`stop`,`-t`,`0`,t]).catch(()=>{})}export{DOCKER_SANDBOX_LABEL,runDockerBaseSetup,startDockerContainer,stopDockerContainerIfRunning};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{toErrorMessage}from"#shared/errors.js";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{runDockerBaseSetup,startDockerContainer,stopDockerContainerIfRunning}from"#execution/sandbox/bindings/docker-container.js";import{setDockerNetworkPolicy}from"#execution/sandbox/bindings/docker-network.js";import{createDockerSandboxOptionsHash,resolveDockerSandboxOptions}from"#execution/sandbox/bindings/docker-options.js";import{createDockerInternalSession}from"#execution/sandbox/bindings/docker-session.js";import{DOCKER_TEMPLATE_IMAGE_REPOSITORY,commitDockerTemplateImage,dockerImageExists,dockerTemplateImageReference,ensureDockerBaseImage,pruneDockerSandboxTemplates,resolveDockerTemplateMarkerPath,touchDockerTemplateMarker}from"#execution/sandbox/bindings/docker-templates.js";import{buildSandboxDockerfile,dockerfileImageReference,materializeSandboxDockerfile}from"#execution/sandbox/dockerfile.js";import{hydrateSandboxProviderResources,prepareImmutableResources}from"#execution/sandbox/bindings/immutable-resources.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{
|
|
1
|
+
import{randomUUID}from"node:crypto";import{toErrorMessage}from"#shared/errors.js";import{expectDockerSuccess}from"#execution/sandbox/bindings/docker-utils.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{runDockerBaseSetup,startDockerContainer,stopDockerContainerIfRunning}from"#execution/sandbox/bindings/docker-container.js";import{setDockerNetworkPolicy}from"#execution/sandbox/bindings/docker-network.js";import{createDockerSandboxOptionsHash,resolveDockerSandboxOptions}from"#execution/sandbox/bindings/docker-options.js";import{createDockerInternalSession}from"#execution/sandbox/bindings/docker-session.js";import{DOCKER_TEMPLATE_IMAGE_REPOSITORY,commitDockerTemplateImage,dockerImageExists,dockerTemplateImageReference,ensureDockerBaseImage,pruneDockerSandboxTemplates,resolveDockerTemplateMarkerPath,touchDockerTemplateMarker}from"#execution/sandbox/bindings/docker-templates.js";import{buildSandboxDockerfile,dockerfileImageReference,materializeSandboxDockerfile}from"#execution/sandbox/dockerfile.js";import{hydrateSandboxProviderResources,prepareImmutableResources}from"#execution/sandbox/bindings/immutable-resources.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{createSandboxProviderIdentity}from"#execution/sandbox/provider-identity.js";import{isSandboxPreparedArtifactRecord,sandboxProviderResourceIdentity}from"#shared/sandbox-provider.js";import{SandboxTemplateNotProvisionedError}from"#shared/sandbox-template-error.js";const DOCKER_PROVIDER_NAME=`docker`;function createDockerSandboxProvider(e,t){let n=t??createDockerCli(),r=e??{},i=resolveDockerSandboxOptions(r),a=createDockerSandboxOptionsHash(i),o;function ensureDaemon(){return o??=assertDockerDaemonAvailable(n).catch(e=>{throw o=void 0,e}),o}async function inspectContainerRunning(e){let t=await n.run([`container`,`inspect`,`--format`,`{{.State.Running}}`,e]);return t.exitCode===0?t.stdout.trim()===`true`:void 0}async function openDockerSession(e,t,r,a,o){await ensureDaemon();let s=requirePreparedDockerArtifact(r);if(!await dockerImageExists(n,s.imageReference))throw new SandboxTemplateNotProvisionedError({providerName:DOCKER_PROVIDER_NAME,templateKey:s.imageReference});let c=await inspectContainerRunning(a);if(c===void 0){if(!o)throw Error(`Docker sandbox session container "${a}" no longer exists.`);try{await startDockerContainer({cli:n,containerName:a,image:s.imageReference,initialNetworkPolicy:t?.networkPolicy??`allow-all`,options:i,role:`session`,tags:{agent:e.session.id,sessionId:e.session.id}}),c=!0}catch(e){if(c=/is already in use/u.test(toErrorMessage(e))?await inspectContainerRunning(a):void 0,c===void 0)throw e}}c||expectDockerSuccess(await n.run([`start`,a]),`restart sandbox session container "${a}"`);let l=await resolveDockerHandleIdentity(n,a);return{sandbox:buildSandboxSession(createDockerInternalSession({cli:n,containerIdentity:l}),e=>setDockerNetworkPolicy(n,l,e)),async onSandboxDelete(){await stopDockerContainerIfRunning(n,l),expectDockerSuccess(await n.run([`rm`,`-f`,l]),`delete sandbox session container "${a}"`)},async onSandboxStop(){await stopDockerContainerIfRunning(n,l)},async onRuntimeShutdown(){await stopDockerContainerIfRunning(n,l)}}}return{async prepare(e){e.log?.(`checking Docker daemon`),await ensureDaemon();let t=await materializeSandboxDockerfile({files:e.files,storagePath:e.storagePath}),o=createSandboxProviderIdentity({dockerfile:t?.contentHash,optionsHash:a,resources:sandboxProviderResourceIdentity(e.resources),sourceRevision:e.sourceRevision,version:2}).slice(0,24),s={optionsHash:a,templateKey:o},c=dockerTemplateImageReference(s),l=e.resources.source,u=l.kind===`materialized`?await prepareImmutableResources({storagePath:e.storagePath,provider:DOCKER_PROVIDER_NAME,resourcesKey:l.key,sourcePath:l.path}):void 0,d=resolveDockerTemplateMarkerPath(e.storagePath,s);if(e.log?.(`checking cached template image "${c}"`),await dockerImageExists(n,c))return e.log?.(`reusing cached template image`),await touchDockerTemplateMarker(d,c),{imageReference:c};let f=i.image;t===void 0?(e.log?.(`checking base image "${i.image}"`),await ensureDockerBaseImage(n,i)):(f=dockerfileImageReference({dockerfile:t,templateKey:o}),e.log?.(`building sandbox Dockerfile "${t.path}"`),await buildSandboxDockerfile({cli:n,dockerfile:t,imageReference:f}));let p=`${o}-build-${randomUUID().slice(0,8)}`;e.log?.(`starting template build container`),await startDockerContainer({cli:n,containerName:p,image:f,initialNetworkPolicy:`allow-all`,options:i,resourcesPath:u,role:`template-build`});try{let t=await resolveDockerHandleIdentity(n,p);e.log?.(`preparing base runtime inside container`),await runDockerBaseSetup(n,t);let i=buildSandboxSession(createDockerInternalSession({cli:n,containerIdentity:t}),e=>setDockerNetworkPolicy(n,t,e));await hydrateSandboxProviderResources({copySkills:!0,log:e.log,resources:e.resources,session:i}),r.prepare!==void 0&&(e.log?.(`running sandbox preparation`),await r.prepare(createLoggingSandboxSession({log:e.log,session:i}))),e.log?.(`stopping template build container`),expectDockerSuccess(await n.run([`stop`,`-t`,`0`,t]),`stop template build container "${p}"`),e.log?.(`committing template image "${c}"`),await commitDockerTemplateImage({cli:n,containerIdentity:t,imageReference:c,templateKey:o})===`reused`&&e.log?.(`reusing concurrently published template image`),await touchDockerTemplateMarker(d,c)}finally{await n.run([`rm`,`-f`,p]).catch(()=>{}),t!==void 0&&await n.run([`rmi`,f]).catch(()=>{})}return{imageReference:c}},async resume(e,t,n){let r=requireDockerSessionState(n);if(r.generation!==dockerGeneration(t,a))throw Error(`Docker sandbox session state is incompatible with this environment.`);return await openDockerSession(e,void 0,t,r.containerName,!1)},async start(e,t,n){let r=dockerSessionName(e.session.id,t,n,a);return{handle:await openDockerSession(e,t,n,r,!0),state:{containerName:r,generation:dockerGeneration(n,a),version:2}}}}}function dockerGeneration(e,t){return createSandboxProviderIdentity({artifact:e,environment:t,version:1})}function dockerSessionName(e,t,n,r){return`eve-sbx-${createSandboxProviderIdentity({artifact:n,environment:r,open:{networkPolicy:t?.networkPolicy},sessionId:e,version:1}).slice(0,32)}`}function requirePreparedDockerArtifact(e){if(!isSandboxPreparedArtifactRecord(e)||typeof e.imageReference!=`string`)throw Error(`Invalid prepared Docker artifact.`);return{imageReference:e.imageReference}}function requireDockerSessionState(e){if(!isSandboxPreparedArtifactRecord(e)||e.version!==2||typeof e.containerName!=`string`||typeof e.generation!=`string`)throw Error(`Invalid Docker sandbox session state.`);return{containerName:e.containerName,generation:e.generation,version:2}}async function resolveDockerHandleIdentity(e,t){let n=await e.run([`container`,`inspect`,`--format`,`{{.Id}}`,t]);expectDockerSuccess(n,`resolve sandbox container identity for "${t}"`);let r=n.stdout.trim();if(r.length===0)throw Error(`Docker returned an empty identity for sandbox container "${t}".`);return r}export{DOCKER_PROVIDER_NAME,DOCKER_TEMPLATE_IMAGE_REPOSITORY,createDockerSandboxProvider,pruneDockerSandboxTemplates};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mkdir,readFile,rm,writeFile}from"node:fs/promises";import{dirname}from"node:path";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{
|
|
1
|
+
import{mkdir,readFile,rm,writeFile}from"node:fs/promises";import{dirname}from"node:path";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{SANDBOX_AGENT_ENV,buildSandboxSession}from"#execution/sandbox/session.js";import{createFileBackedInternalSandboxSession,pathExists}from"#execution/sandbox/bindings/local-provider-utils.js";import{adaptMultiplexedCommandToSandboxProcess}from"#execution/sandbox/multiplexed-command.js";let justBashModulePromise;async function loadJustBashModule(e){return justBashModulePromise??=e.host.loadOptionalPackage({autoInstall:e.autoInstall,importModule:async()=>await import(`just-bash`),missingMessage:"The just-bash sandbox provider requires the `just-bash` package, which is not bundled with eve. Install it in your application (for example `pnpm add -D just-bash`), or use DockerSandbox or DefaultSandbox instead.",packageName:`just-bash`,ignoredOptionalDependencies:[`@mongodb-js/zstd`,`node-liblzma`]}).catch(e=>{throw justBashModulePromise=void 0,e}),await justBashModulePromise}async function createBashSandbox(e){let t=await loadJustBashModule({autoInstall:e.autoInstall,host:e.host}),{ReadWriteFs:n,Sandbox:r}=t,i=resolveLocalSandboxFilesystemRootPath(e.rootPath),a=resolveLocalSandboxMetadataPath(e.rootPath),o=await readLocalMetadata(a);await mkdir(i,{recursive:!0});let s=new n({allowSymlinks:!0,maxFileReadSize:2**53-1,root:i}),c=s;if(e.filesystem!==void 0)try{c=await e.filesystem({defaultFilesystem:s,resolveProjectPath:e.host.resolveProjectPath,storagePath:e.storagePath,justBash:t})}catch(e){throw Error(`Failed to create the custom just-bash filesystem.`,{cause:e})}await ensureLocalSandboxDirectories(c);let l=await r.create({cwd:WORKSPACE_ROOT,customCommands:e.customCommands===void 0?void 0:[...e.customCommands],env:o===null?void 0:{...o.env},fs:c,network:{dangerouslyAllowFullInternetAccess:!0}});return{async captureState(){return await writeLocalMetadata(a,{env:{...l.bashEnvInstance.getEnv()},version:1}),{rootPath:e.rootPath}},async dispose(){await l.stop()},async readFileBytes(e){let t;try{t=await c.readFileBuffer(e)}catch{return null}return Buffer.from(t)},async removePath(e){await c.rm(e.path,{force:e.force,recursive:e.recursive})},rootPath:e.rootPath,sessionKey:e.sessionKey,async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=e.workingDirectory===void 0?e.command:`( cd ${shellQuote(e.workingDirectory)} && ${e.command} )`,n=await l.runCommand({args:[t],cmd:`eval`,detached:!0,env:{...SANDBOX_AGENT_ENV,...e.env},signal:e.abortSignal});return adaptMultiplexedCommandToSandboxProcess({command:n,getOutput:e=>e.type})},async writeFiles(e){for(let t of e){let e=dirname(t.path);await c.mkdir(e,{recursive:!0}),await c.writeFile(t.path,t.content)}}}}function createJustBashHandle(e){return{sandbox:buildSandboxSession(createFileBackedInternalSandboxSession({sandbox:e})),async onSandboxDelete(){await e.dispose(),await rm(e.rootPath,{force:!0,recursive:!0})},async onSandboxStop(){await e.dispose()},async onRuntimeShutdown(){await e.dispose()}}}function resolveLocalSandboxFilesystemRootPath(e){return`${e}/fs`}function resolveLocalSandboxMetadataPath(e){return`${e}/metadata.json`}async function ensureLocalSandboxDirectories(e){await e.mkdir(WORKSPACE_ROOT,{recursive:!0})}async function readLocalMetadata(e){if(!await pathExists(e))return null;let t=JSON.parse(await readFile(e,`utf8`));return!isRecord(t)||t.version!==1||!isStringRecord(t.env)?null:{env:t.env,version:1}}async function writeLocalMetadata(e,t){await mkdir(dirname(e),{recursive:!0}),await writeFile(e,`${JSON.stringify(t,null,2)}\n`)}function isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isStringRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&Object.values(e).every(e=>typeof e==`string`)}export{createBashSandbox,createJustBashHandle};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{mkdir,readdir,rename,rm,stat}from"node:fs/promises";import"node:fs";import{dirname,join}from"node:path";import{resolveSandboxCacheDirectory}from"#internal/application/paths.js";import{withToolSessionSandboxes}from"#execution/tool-session/sandbox.js";import{copyDirectoryAtomically,createFileBackedInternalSandboxSession,pathExists,resolveLocalProviderSessionRootPath,resolveLocalProviderTemplateRootPath,resolveLocalProviderTemplatesDirectory,touchDirectory,writeSandboxSeedFiles}from"#execution/sandbox/bindings/local-provider-utils.js";import{LOCAL_SANDBOX_TEMPLATE_RECENT_WINDOW_MS,LOCAL_SANDBOX_TEMPLATE_RETAIN_COUNT,selectStaleTemplateEntries}from"#execution/sandbox/bindings/local-template-prune.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{
|
|
1
|
+
import{randomUUID}from"node:crypto";import{mkdir,readdir,rename,rm,stat}from"node:fs/promises";import"node:fs";import{dirname,join}from"node:path";import{resolveSandboxCacheDirectory}from"#internal/application/paths.js";import{withToolSessionSandboxes}from"#execution/tool-session/sandbox.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{copyDirectoryAtomically,createFileBackedInternalSandboxSession,pathExists,resolveLocalProviderSessionRootPath,resolveLocalProviderTemplateRootPath,resolveLocalProviderTemplatesDirectory,touchDirectory,writeSandboxSeedFiles}from"#execution/sandbox/bindings/local-provider-utils.js";import{LOCAL_SANDBOX_TEMPLATE_RECENT_WINDOW_MS,LOCAL_SANDBOX_TEMPLATE_RETAIN_COUNT,selectStaleTemplateEntries}from"#execution/sandbox/bindings/local-template-prune.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{createSandboxProviderIdentity}from"#execution/sandbox/provider-identity.js";import{isSandboxPreparedArtifactRecord,providerResourceTargetFiles,sandboxProviderResourceIdentity}from"#shared/sandbox-provider.js";import{SandboxTemplateNotProvisionedError}from"#shared/sandbox-template-error.js";import{createBashSandbox,createJustBashHandle}from"#execution/sandbox/bindings/just-bash-runtime.js";const JUST_BASH_CACHE_DIRECTORY_NAME=`just-bash`,JUST_BASH_PROVIDER_NAME=`just-bash`;function createJustBashSandboxProvider(e=void 0){let t=e??{},n=t.autoInstall??!0,r={autoInstall:n,customCommands:t.customCommands,filesystem:t.filesystem,version:2};return withToolSessionSandboxes({async prepare(e){let i=createSandboxProviderIdentity({...r,resources:sandboxProviderResourceIdentity(e.resources),sourceRevision:e.sourceRevision}).slice(0,24),a=resolveTemplateRootPath(e.storagePath,i);if(await pathExists(a))return await touchDirectory(a),e.log?.(`reusing cached template filesystem`),{templateKey:i};let o=`${a}.${randomUUID()}.tmp`,s=!1,c=await createBashSandbox({autoInstall:n,host:e.host,rootPath:o,sessionKey:`prepare-${i}`,storagePath:e.storagePath}),l=buildSandboxSession(createFileBackedInternalSandboxSession({sandbox:c}));try{await writeSandboxSeedFiles(l,providerResourceTargetFiles(e.resources)),t.prepare!==void 0&&(e.log?.(`running sandbox preparation`),await t.prepare(createLoggingSandboxSession({log:e.log,session:l}))),await c.captureState(),await mkdir(dirname(a),{recursive:!0});try{await rename(o,a),s=!0}catch(e){if(await pathExists(a))return{templateKey:i};throw e}}finally{await c.dispose(),s||await rm(o,{force:!0,recursive:!0})}return{templateKey:i}},async resume(e,n,r){let i=requirePreparedJustBashArtifact(n),a=requireJustBashSessionState(r),o=createSandboxProviderIdentity({artifact:i,version:1}),s=sessionRootPath(e,i);if(a.generation!==o||a.rootPath!==s)throw Error(`just-bash session state is incompatible with this environment.`);if(!await pathExists(a.rootPath))throw Error(`just-bash session root "${a.rootPath}" no longer exists.`);return await openHandle(e,a.rootPath,t)},async start(e,n,r){let i=requirePreparedJustBashArtifact(r),a=sessionRootPath(e,i);return await ensureSessionRoot(resolveTemplateRootPath(e.storagePath,i.templateKey),a),{handle:await openHandle(e,a,t),state:{generation:createSandboxProviderIdentity({artifact:i,version:1}),rootPath:a,version:2}}}},{releaseHandle:e=>e.onSandboxStop()})}function sessionRootPath(e,t){return resolveSessionRootPath(e.storagePath,createSandboxProviderIdentity({artifact:t,sessionId:e.session.id,version:1}).slice(0,24))}async function ensureSessionRoot(e,t){if(!await pathExists(t)){if(!await pathExists(e))throw new SandboxTemplateNotProvisionedError({providerName:JUST_BASH_PROVIDER_NAME,templateKey:e});await copyDirectoryAtomically(e,t)}}async function openHandle(e,t,n){let r=await createBashSandbox({autoInstall:n.autoInstall??!0,customCommands:n.customCommands,filesystem:n.filesystem,host:e.host,rootPath:t,sessionKey:e.session.id,storagePath:e.storagePath});return createJustBashHandle(r)}async function pruneJustBashSandboxTemplates(e){let t=resolveLocalProviderTemplatesDirectory(resolveSandboxCacheDirectory(e.appRoot),JUST_BASH_CACHE_DIRECTORY_NAME),n=e.now??Date.now(),r=e.recentWindowMs??LOCAL_SANDBOX_TEMPLATE_RECENT_WINDOW_MS,i=e.retainCount??LOCAL_SANDBOX_TEMPLATE_RETAIN_COUNT,a;try{a=await readdir(t,{withFileTypes:!0})}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}let o=await Promise.all(a.filter(e=>e.isDirectory()).map(async e=>{let n=join(t,e.name);return{isTemporary:e.name.endsWith(`.tmp`),mtimeMs:(await stat(n)).mtimeMs,path:n}})),s=selectStaleTemplateEntries(o.filter(e=>!e.isTemporary),{now:n,recentWindowMs:r,retainCount:i}),c=selectStaleTemplateEntries(o.filter(e=>e.isTemporary),{now:n,recentWindowMs:r,retainCount:0});await Promise.all([...s,...c].map(async e=>await rm(e.path,{force:!0,recursive:!0})))}function requirePreparedJustBashArtifact(e){if(!isSandboxPreparedArtifactRecord(e)||typeof e.templateKey!=`string`)throw Error(`Invalid prepared just-bash artifact.`);return{templateKey:e.templateKey}}function requireJustBashSessionState(e){if(!isSandboxPreparedArtifactRecord(e)||e.version!==2||typeof e.generation!=`string`||typeof e.rootPath!=`string`)throw Error(`Invalid just-bash session state.`);return{generation:e.generation,rootPath:e.rootPath,version:2}}function resolveTemplateRootPath(e,t){return resolveLocalProviderTemplateRootPath(e,JUST_BASH_CACHE_DIRECTORY_NAME,t)}function resolveSessionRootPath(e,t){return resolveLocalProviderSessionRootPath(e,JUST_BASH_CACHE_DIRECTORY_NAME,t)}export{JUST_BASH_PROVIDER_NAME,createJustBashSandboxProvider,pruneJustBashSandboxTemplates};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID}from"node:crypto";import{mkdir,rename,rm}from"node:fs/promises";import{dirname}from"node:path";import{withDevelopmentSandboxMetadataPathTag}from"#execution/sandbox/development-run.js";import{createFileBackedInternalSandboxSession,touchDirectory}from"#execution/sandbox/bindings/local-provider-utils.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{buildSandboxDockerfile,dockerfileImageReference,publishDockerImageForMicrosandbox}from"#execution/sandbox/dockerfile.js";import{hydrateSandboxProviderResources,prepareImmutableResources}from"#execution/sandbox/bindings/immutable-resources.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{
|
|
1
|
+
import{randomUUID}from"node:crypto";import{mkdir,rename,rm}from"node:fs/promises";import{dirname}from"node:path";import{withDevelopmentSandboxMetadataPathTag}from"#execution/sandbox/development-run.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{createFileBackedInternalSandboxSession,touchDirectory}from"#execution/sandbox/bindings/local-provider-utils.js";import{assertDockerDaemonAvailable,createDockerCli}from"#execution/sandbox/bindings/docker-cli.js";import{buildSandboxDockerfile,dockerfileImageReference,publishDockerImageForMicrosandbox}from"#execution/sandbox/dockerfile.js";import{hydrateSandboxProviderResources,prepareImmutableResources}from"#execution/sandbox/bindings/immutable-resources.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{isSandboxPreparedArtifactRecord}from"#shared/sandbox-provider.js";import{SandboxTemplateNotProvisionedError}from"#shared/sandbox-template-error.js";import{MICROSANDBOX_METADATA_VERSION,readSessionMetadata,readTemplateMetadata,resolveMicrosandboxMetadataPath,writeTemplateMetadata}from"#execution/sandbox/bindings/microsandbox-metadata.js";import{connectMicrosandbox,createPreparedMicrosandbox,createProviderName,createStableHash,doesPathExist,loadMicrosandboxModule,removeSnapshotIfExists,sandboxExists,snapshotExists}from"#execution/sandbox/bindings/microsandbox-runtime.js";import{resolveMicrosandboxSessionRootPath,resolveMicrosandboxTemplateRootPath}from"#execution/sandbox/bindings/microsandbox-templates.js";const activeMicrosandboxSessionHandles=new Map;async function prewarmMicrosandboxTemplate(e){e.context.log?.(`loading microsandbox runtime`);let t=await loadMicrosandboxModule({host:e.context.host,log:e.context.log,options:e.options}),n=e.context.storagePath,r=resolveMicrosandboxTemplateRootPath(n,e.templateKey),i=resolveMicrosandboxMetadataPath(r);e.context.log?.(`checking cached snapshot`);let a=await readTemplateMetadata(i);if(a?.optionsHash===e.optionsHash&&await snapshotExists(t,a.snapshotName))return e.context.log?.(`reusing cached snapshot`),await touchDirectory(r),microsandboxTemplateArtifact(a);let o=createProviderName(`eve-sbx-tpl`,e.templateKey,e.optionsHash),s=`${r}.${randomUUID()}.tmp`,c=createProviderName(`eve-sbx-tpl-tmp`,`${e.templateKey}:${randomUUID()}`);await removeSnapshotIfExists(t,o),await rm(s,{force:!0,recursive:!0}),await mkdir(s,{recursive:!0});let l=e.options;if(e.dockerfile!==void 0){let t=createDockerCli();await assertDockerDaemonAvailable(t);let n=dockerfileImageReference({dockerfile:e.dockerfile,templateKey:e.templateKey});e.context.log?.(`building sandbox Dockerfile "${e.dockerfile.path}"`),await buildSandboxDockerfile({cli:t,dockerfile:e.dockerfile,imageReference:n}),e.context.log?.(`publishing Dockerfile image for microsandbox`);let r=await publishDockerImageForMicrosandbox({cli:t,imageReference:n});l={...e.options,image:r,pullPolicy:`always`}}let u=e.context.resources.source,d=u.kind===`materialized`?await prepareImmutableResources({storagePath:e.context.storagePath,provider:e.providerName,resourcesKey:u.key,sourcePath:u.path}):void 0;e.context.log?.(`creating template VM from image "${l.image}"`);let f=await createPreparedMicrosandbox({log:e.context.log,module:t,name:c,networkPolicy:`allow-all`,options:l,resourcesPath:d,sessionKey:e.templateKey,setupBaseRuntime:!0,tags:void 0}),p=buildSandboxSession(createMicrosandboxInternalSession(f),async e=>{await f.setNetworkPolicy(e)});try{await hydrateSandboxProviderResources({copySkills:!0,log:e.context.log,resources:e.context.resources,session:p}),e.prepare!==void 0&&(e.context.log?.(`running sandbox preparation`),await e.prepare(createLoggingSandboxSession({log:e.context.log,session:p}))),e.context.log?.(`snapshotting template VM`),await f.stopAndSnapshot(o),await writeTemplateMetadata(resolveMicrosandboxMetadataPath(s),{image:e.dockerfile===void 0?void 0:l.image,optionsHash:e.optionsHash,snapshotName:o,version:MICROSANDBOX_METADATA_VERSION}),await mkdir(dirname(r),{recursive:!0}),await rm(r,{force:!0,recursive:!0});try{await rename(s,r)}catch(e){if(await doesPathExist(r)){let e=await readTemplateMetadata(i);if(e!==null)return microsandboxTemplateArtifact(e)}throw e}}finally{await f.removePersisted(),await rm(s,{force:!0,recursive:!0}).catch(()=>{})}return microsandboxTemplateArtifact({image:e.dockerfile===void 0?void 0:l.image,optionsHash:e.optionsHash,snapshotName:o,version:MICROSANDBOX_METADATA_VERSION})}async function createMicrosandboxHandle(e){let t=requirePreparedMicrosandboxTemplate(e.artifact,e.providerName),n=e.sessionIdentity??createStableHash(`${e.context.session.id}:${t.snapshotName}:${e.optionsHash}`).slice(0,32),r=resolveMicrosandboxSessionRootPath(e.context.storagePath,n),i=resolveMicrosandboxMetadataPath(r),a=await readSessionMetadata(i),o=resolveMicrosandboxImage(a,t,e.options),s={...e.options,...o,networkPolicy:e.runtimeOptions?.networkPolicy},c=await loadMicrosandboxModule({host:e.context.host,options:s}),l=createActiveMicrosandboxSessionKey(r,e.optionsHash),u=activeMicrosandboxSessionHandles.get(l),d={optionsHash:e.optionsHash,sessionIdentity:n,version:3};if(u!==void 0)return{handle:u,state:d};let f=withDevelopmentSandboxMetadataPathTag({sessionId:e.context.session.id},i);if(a?.optionsHash===e.optionsHash&&(await sandboxExists(c,a.sandboxName)||a.stateSnapshotName!==void 0&&await snapshotExists(c,a.stateSnapshotName))){let t=await connectMicrosandbox({metadata:a,metadataPath:i,module:c,options:s,sessionKey:e.context.session.id,tags:f});if(t!==null)return{handle:cacheHandle(l,createHandle(t,e.optionsHash,()=>{activeMicrosandboxSessionHandles.delete(l)})),state:d}}if(e.sessionIdentity!==void 0&&e.createIfMissing===!1)throw Error(`microsandbox session "${e.sessionIdentity}" is no longer available to resume.`);if(t.optionsHash!==e.optionsHash||!await snapshotExists(c,t.snapshotName))throw new SandboxTemplateNotProvisionedError({providerName:e.providerName,templateKey:t.snapshotName});let p=createProviderName(`eve-sbx-ses`,n),m=await createPreparedMicrosandbox({fromSnapshot:t.snapshotName,module:c,name:p,networkPolicy:s.networkPolicy,options:s,sessionKey:e.context.session.id,setupBaseRuntime:!1,tags:f});return await m.writeMetadata(i,e.optionsHash),{handle:cacheHandle(l,createHandle(m,e.optionsHash,()=>{activeMicrosandboxSessionHandles.delete(l)})),state:d}}function resolveMicrosandboxImage(e,t,n){return e?.image===void 0?t?.image===void 0?{image:n.image,pullPolicy:n.pullPolicy}:{image:t.image,pullPolicy:`always`}:{image:e.image,pullPolicy:`always`}}function microsandboxTemplateArtifact(e){return{image:e.image??null,optionsHash:e.optionsHash,snapshotName:e.snapshotName,version:e.version}}function requirePreparedMicrosandboxTemplate(e,t){if(!isSandboxPreparedArtifactRecord(e)||e.version!==MICROSANDBOX_METADATA_VERSION||typeof e.optionsHash!=`string`||typeof e.snapshotName!=`string`)throw new SandboxTemplateNotProvisionedError({providerName:t,templateKey:`invalid-artifact`});return{image:typeof e.image==`string`?e.image:void 0,optionsHash:e.optionsHash,snapshotName:e.snapshotName,version:MICROSANDBOX_METADATA_VERSION}}function createHandle(e,t,n){return{sandbox:buildSandboxSession(createMicrosandboxInternalSession(e),async t=>{await e.setNetworkPolicy(t)}),async onSandboxDelete(){await e.shutdown(),await e.removePersisted(),n?.()},async onSandboxStop(){await e.stop(),n?.()},async onRuntimeShutdown(){n?.(),await e.shutdown()}}}function createMicrosandboxInternalSession(e){return createFileBackedInternalSandboxSession({sandbox:e})}function createActiveMicrosandboxSessionKey(e,t){return`${e}\0${t}`}function cacheHandle(e,t){return activeMicrosandboxSessionHandles.set(e,t),t}export{createMicrosandboxHandle,prewarmMicrosandboxTemplate};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createHash,randomUUID}from"node:crypto";import{access}from"node:fs/promises";import{posix}from"node:path";import{withDevelopmentSandboxTags}from"#execution/sandbox/development-run.js";import{importInstalledEnginePackage,isEveDevEnvironment}from"#internal/application/optional-package-install.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{assertMicrosandboxPlatformCandidate,ensureMicrosandboxBaseRuntime}from"#execution/sandbox/bindings/microsandbox-platform.js";import{MICROSANDBOX_METADATA_VERSION,createMicrosandboxSessionMetadata,writeSessionMetadata}from"#execution/sandbox/bindings/microsandbox-metadata.js";import{MICROSANDBOX_USER}from"#execution/sandbox/bindings/microsandbox-options.js";import{createMicrosandboxWithProgress}from"#execution/sandbox/bindings/microsandbox-create.js";import{applyMicrosandboxNetwork,createMicrosandboxNetworkPlan,createTransformBrokerEnvironment}from"#execution/sandbox/bindings/microsandbox-network.js";import{adaptMicrosandboxExecToSandboxProcess}from"#execution/sandbox/bindings/microsandbox-process.js";import{isMicrosandboxNotFoundError,isMicrosandboxNotFoundError as isMicrosandboxNotFoundError$1,isMicrosandboxSnapshotSourceRunningError,isMicrosandboxStillRunningError,removeSnapshotIfExists,removeSnapshotIfExists as removeSnapshotIfExists$1,sandboxExists,snapshotExists,snapshotExists as snapshotExists$1}from"#execution/sandbox/bindings/microsandbox-provider-state.js";const MICROSANDBOX_PACKAGE_NAME=`microsandbox`,MICROSANDBOX_INSTALL_SPECIFIER=`${MICROSANDBOX_PACKAGE_NAME}@0.5.5`,MICROSANDBOX_STOP_TIMEOUT_MS=1e4,MICROSANDBOX_HOME=`/home/${MICROSANDBOX_USER}`;var MicrosandboxVm=class{#e;#t;#n;#r;#i;#a;#o;constructor(e,t,n,r,i,a,o){this.#e=e,this.#i=t,this.#a=n,this.#n=r,this.#t=i,this.#r=a,this.#o=o}get id(){return this.#e.sessionKey}get name(){return this.#a}async captureState(e){if(this.#r=e,isEveDevEnvironment())return this.#t!==void 0&&await this.writeMetadata(this.#t,e),createMicrosandboxSessionMetadata({networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:this.#o});let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`);return await this.stopAndSnapshot(n),this.#o=n,this.#t!==void 0&&await this.writeMetadata(this.#t,e),t!==void 0&&await removeSnapshotIfExists$1(this.#e.module,t),createMicrosandboxSessionMetadata({networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:n})}async detach(){await this.#i.detach().catch(()=>{})}async shutdown(){await this.#i.stop().catch(()=>{}),await this.detach()}async stop(){await this.#i.stop(),await this.detach()}async readFileBytes(e){try{let t=this.#i.fs();return await t.exists(e)?Buffer.from(await t.read(e)):null}catch{return null}}async removePath(e){let t=`${e.force===!0?`f`:``}${e.recursive===!0?`r`:``}`,n=`${t.length>0?`rm -${t}`:`rm`} -- ${shellQuote(e.path)}`;await this.runInternalCommand({abortSignal:e.abortSignal,command:n,user:MICROSANDBOX_USER})}async removePersisted(){await removeSandboxIfExists(this.#e.module,this.#a);let e=this.#o;e!==void 0&&(await removeSnapshotIfExists$1(this.#e.module,e),this.#o=void 0)}async setNetworkPolicy(e){let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`),r=this.#a;await this.stopAndSnapshot(n),await removeSandboxIfExists(this.#e.module,r);let i=createProviderName(`eve-sbx-ses`,`${this.#e.sessionKey}:${randomUUID()}`);this.#i=await createMicrosandbox({fromSnapshot:n,module:this.#e.module,name:i,networkPolicy:e,options:this.#e.options,tags:this.#e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT}),this.#a=i,this.#n=e,this.#o=void 0,this.#t!==void 0&&this.#r!==void 0&&await this.writeMetadata(this.#t,this.#r),await removeSnapshotIfExists$1(this.#e.module,n),t!==void 0&&await removeSnapshotIfExists$1(this.#e.module,t)}async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t={...this.#e.options.env,HOME:MICROSANDBOX_HOME,...createTransformBrokerEnvironment(createMicrosandboxNetworkPlan(this.#n)),...e.env},n=await this.#i.execStreamWith(`bash`,n=>n.args([`-lc`,e.command]).cwd(e.workingDirectory??WORKSPACE_ROOT).envs(t).user(MICROSANDBOX_USER));return e.abortSignal!==void 0&&e.abortSignal.addEventListener(`abort`,()=>{n.kill().catch(()=>{})},{once:!0}),adaptMicrosandboxExecToSandboxProcess(n)}async stopAndSnapshot(e){await this.#i.stop().catch(()=>{}),await stopAndSnapshotMicrosandboxSandbox(this.#e.module,this.#a,e)}async writeFiles(e){let t=this.#i.fs();for(let n of e){let e=posix.dirname(n.path);await this.runInternalCommand({command:`mkdir -p ${shellQuote(e)}`,user:MICROSANDBOX_USER}),await t.write(n.path,n.content),await this.runInternalCommand({command:`chown ${MICROSANDBOX_USER}:${MICROSANDBOX_USER} ${shellQuote(n.path)}`,user:`root`})}}async writeMetadata(e,t){this.#t=e,this.#r=t,await writeSessionMetadata(e,{image:this.#e.options.image,networkPolicy:this.#n,optionsHash:t,sandboxName:this.#a,stateSnapshotName:this.#o,version:MICROSANDBOX_METADATA_VERSION})}async runInternalCommand(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=await this.#i.execWith(`bash`,t=>t.args([`-lc`,e.command]).cwd(WORKSPACE_ROOT).user(e.user));if(t.code!==0){let n=e.failureMessage??`Microsandbox command failed.`;throw Error(`${n} ${t.stderr()}`.trim())}}};async function createPreparedMicrosandbox(e){let t=e.setupBaseRuntime?`allow-all`:e.networkPolicy,n=await createMicrosandbox({fromSnapshot:e.fromSnapshot,log:e.log,module:e.module,name:e.name,networkPolicy:t,options:e.options,resourcesPath:e.resourcesPath,tags:e.tags,user:e.setupBaseRuntime?void 0:MICROSANDBOX_USER,workdir:e.setupBaseRuntime?`/`:WORKSPACE_ROOT}),r=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.name,t);return e.setupBaseRuntime&&(await withProgressHeartbeat(`preparing base runtime inside VM`,e.log,async()=>{await ensureMicrosandboxBaseRuntime(n,{log:e.log})}),e.networkPolicy!==void 0&&e.networkPolicy!==`allow-all`&&(e.log?.(`applying network policy`),await r.setNetworkPolicy(e.networkPolicy))),r}async function connectMicrosandbox(e){let t;try{t=await e.module.Sandbox.get(e.metadata.sandboxName)}catch(t){if(!isMicrosandboxNotFoundError$1(t))throw t;return e.metadata.stateSnapshotName===void 0?null:await restoreMicrosandboxSessionSnapshot(e)}if(t.status!==`running`&&t.status!==`draining`&&e.metadata.stateSnapshotName!==void 0)return await restoreMicrosandboxSessionSnapshot(e);let n=t.status===`running`||t.status===`draining`?await t.connectWithTimeout(1e4):await t.startDetached();return new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.metadata.sandboxName,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName)}async function restoreMicrosandboxSessionSnapshot(e){if(e.metadata.stateSnapshotName===void 0||!await snapshotExists$1(e.module,e.metadata.stateSnapshotName))return null;let t=createProviderName(`eve-sbx-ses`,`${e.sessionKey}:${randomUUID()}`),n=await createMicrosandbox({fromSnapshot:e.metadata.stateSnapshotName,module:e.module,name:t,networkPolicy:e.metadata.networkPolicy,options:e.options,tags:e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT});await removeSandboxIfExists(e.module,e.metadata.sandboxName);let r=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,t,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName);return await r.writeMetadata(e.metadataPath,e.metadata.optionsHash),r}const MICROSANDBOX_MISSING_PACKAGE_MESSAGE=`The microsandbox sandbox provider requires the \`microsandbox\` package, which is not bundled with eve. Install it in your application (for example \`pnpm add -D ${MICROSANDBOX_INSTALL_SPECIFIER}\`), or use DockerSandbox or VercelSandbox instead.`;async function loadMicrosandboxModule(e){e.log?.(`checking microsandbox platform support`),await assertMicrosandboxPlatformCandidate();let t=await withProgressHeartbeat(`loading microsandbox npm package`,e.log,()=>e.host.loadOptionalPackage({autoInstall:e.options.setup.autoInstall,importModule:async()=>await import(`microsandbox`),installPackageName:MICROSANDBOX_INSTALL_SPECIFIER,missingMessage:MICROSANDBOX_MISSING_PACKAGE_MESSAGE,packageName:MICROSANDBOX_PACKAGE_NAME}));if(e.log?.(`checking microsandbox VM runtime`),!t.isInstalled()){if(!e.options.setup.autoInstall||!isEveDevEnvironment())throw Error("The microsandbox VM runtime is not installed. Run `npx microsandbox install`, set MSB_PATH for a custom install, or let `eve dev` install it automatically with microsandbox({ setup: { autoInstall: true } }).");await withProgressHeartbeat(`installing microsandbox VM runtime`,e.log,async()=>{await t.setup().skipVerify(e.options.setup.skipVerify).install()})}return e.log?.(`microsandbox runtime ready`),t}async function withProgressHeartbeat(e,t,n){if(t?.(e),t===void 0)return await n();let r=Date.now(),i=setInterval(()=>{t(`${e} (${Math.round((Date.now()-r)/1e3)}s elapsed)`)},1e4);i.unref?.();try{return await n()}finally{clearInterval(i)}}async function loadMicrosandboxWithoutInstall(e){try{let t=await importInstalledEnginePackage({appRoot:e,packageName:MICROSANDBOX_PACKAGE_NAME});return t.isInstalled()?t:null}catch{return null}}async function stopAndSnapshotMicrosandboxSandbox(e,t,n){for(let r=0;r<3;r+=1){let i=await e.Sandbox.get(t);await i.stopWithTimeout(r===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{});try{await i.snapshot(n);return}catch(e){if(!isMicrosandboxSnapshotSourceRunningError(e)||r===2)throw e;await i.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250))}}}function createProviderName(e,t,n=``){return`${e}-${createStableHash(`${t}:${n}`).slice(0,32)}`}function createStableHash(e){return createHash(`sha256`).update(e).digest(`hex`)}async function doesPathExist(e){try{return await access(e),!0}catch{return!1}}async function createMicrosandbox(e){let t=e.module.Sandbox.builder(e.name).cpus(e.options.cpus).detached(!0).envs({...e.options.env,HOME:MICROSANDBOX_HOME}).labels(resolveMicrosandboxLabels(e.tags)).memory(e.options.memoryMiB).pullPolicy(e.options.pullPolicy).replace().workdir(e.workdir);t=e.fromSnapshot===void 0?t.image(e.options.image):t.fromSnapshot(e.fromSnapshot),e.options.image.startsWith(`127.0.0.1:`)&&(t=t.registry(e=>e.insecure())),e.resourcesPath!==void 0&&(t=t.volume(`/eve/resources`,t=>t.bind(e.resourcesPath).readonly())),e.user!==void 0&&(t=t.user(e.user));let n=e.fromSnapshot===void 0?`image "${e.options.image}"`:`snapshot "${e.fromSnapshot}"`;return await createMicrosandboxWithProgress({builder:applyMicrosandboxNetwork(t,e.networkPolicy),errorType:e.module.MicrosandboxError,log:e.log,source:n})}async function removeSandboxIfExists(e,t){for(let n=0;n<3;n+=1)try{let r=await e.Sandbox.get(t);await r.stopWithTimeout(n===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{}),await r.remove();return}catch(r){if(isMicrosandboxNotFoundError$1(r))return;if(isMicrosandboxStillRunningError(r)&&n<2){await(await e.Sandbox.get(t).catch(()=>null))?.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250));continue}throw r}}function resolveMicrosandboxLabels(e){return{"eve.provider":`microsandbox`,...withDevelopmentSandboxTags(e)}}export{MicrosandboxVm,connectMicrosandbox,createPreparedMicrosandbox,createProviderName,createStableHash,doesPathExist,isMicrosandboxNotFoundError,loadMicrosandboxModule,loadMicrosandboxWithoutInstall,removeSnapshotIfExists,sandboxExists,snapshotExists,stopAndSnapshotMicrosandboxSandbox};
|
|
1
|
+
import{createHash,randomUUID}from"node:crypto";import{access}from"node:fs/promises";import{posix}from"node:path";import{withDevelopmentSandboxTags}from"#execution/sandbox/development-run.js";import{importInstalledEnginePackage,isEveDevEnvironment}from"#internal/application/optional-package-install.js";import{shellQuote}from"#execution/sandbox/shell-quote.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{SANDBOX_AGENT_ENV}from"#execution/sandbox/session.js";import{assertMicrosandboxPlatformCandidate,ensureMicrosandboxBaseRuntime}from"#execution/sandbox/bindings/microsandbox-platform.js";import{MICROSANDBOX_METADATA_VERSION,createMicrosandboxSessionMetadata,writeSessionMetadata}from"#execution/sandbox/bindings/microsandbox-metadata.js";import{MICROSANDBOX_USER}from"#execution/sandbox/bindings/microsandbox-options.js";import{createMicrosandboxWithProgress}from"#execution/sandbox/bindings/microsandbox-create.js";import{applyMicrosandboxNetwork,createMicrosandboxNetworkPlan,createTransformBrokerEnvironment}from"#execution/sandbox/bindings/microsandbox-network.js";import{adaptMicrosandboxExecToSandboxProcess}from"#execution/sandbox/bindings/microsandbox-process.js";import{isMicrosandboxNotFoundError,isMicrosandboxNotFoundError as isMicrosandboxNotFoundError$1,isMicrosandboxSnapshotSourceRunningError,isMicrosandboxStillRunningError,removeSnapshotIfExists,removeSnapshotIfExists as removeSnapshotIfExists$1,sandboxExists,snapshotExists,snapshotExists as snapshotExists$1}from"#execution/sandbox/bindings/microsandbox-provider-state.js";const MICROSANDBOX_PACKAGE_NAME=`microsandbox`,MICROSANDBOX_INSTALL_SPECIFIER=`${MICROSANDBOX_PACKAGE_NAME}@0.5.5`,MICROSANDBOX_STOP_TIMEOUT_MS=1e4,MICROSANDBOX_HOME=`/home/${MICROSANDBOX_USER}`;var MicrosandboxVm=class{#e;#t;#n;#r;#i;#a;#o;constructor(e,t,n,r,i,a,o){this.#e=e,this.#i=t,this.#a=n,this.#n=r,this.#t=i,this.#r=a,this.#o=o}get id(){return this.#e.sessionKey}get name(){return this.#a}async captureState(e){if(this.#r=e,isEveDevEnvironment())return this.#t!==void 0&&await this.writeMetadata(this.#t,e),createMicrosandboxSessionMetadata({networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:this.#o});let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`);return await this.stopAndSnapshot(n),this.#o=n,this.#t!==void 0&&await this.writeMetadata(this.#t,e),t!==void 0&&await removeSnapshotIfExists$1(this.#e.module,t),createMicrosandboxSessionMetadata({networkPolicy:this.#n,optionsHash:e,sandboxName:this.#a,stateSnapshotName:n})}async detach(){await this.#i.detach().catch(()=>{})}async shutdown(){await this.#i.stop().catch(()=>{}),await this.detach()}async stop(){await this.#i.stop(),await this.detach()}async readFileBytes(e){try{let t=this.#i.fs();return await t.exists(e)?Buffer.from(await t.read(e)):null}catch{return null}}async removePath(e){let t=`${e.force===!0?`f`:``}${e.recursive===!0?`r`:``}`,n=`${t.length>0?`rm -${t}`:`rm`} -- ${shellQuote(e.path)}`;await this.runInternalCommand({abortSignal:e.abortSignal,command:n,user:MICROSANDBOX_USER})}async removePersisted(){await removeSandboxIfExists(this.#e.module,this.#a);let e=this.#o;e!==void 0&&(await removeSnapshotIfExists$1(this.#e.module,e),this.#o=void 0)}async setNetworkPolicy(e){let t=this.#o,n=createProviderName(`eve-sbx-state`,`${this.#e.sessionKey}:${randomUUID()}`),r=this.#a;await this.stopAndSnapshot(n),await removeSandboxIfExists(this.#e.module,r);let i=createProviderName(`eve-sbx-ses`,`${this.#e.sessionKey}:${randomUUID()}`);this.#i=await createMicrosandbox({fromSnapshot:n,module:this.#e.module,name:i,networkPolicy:e,options:this.#e.options,tags:this.#e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT}),this.#a=i,this.#n=e,this.#o=void 0,this.#t!==void 0&&this.#r!==void 0&&await this.writeMetadata(this.#t,this.#r),await removeSnapshotIfExists$1(this.#e.module,n),t!==void 0&&await removeSnapshotIfExists$1(this.#e.module,t)}async spawn(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t={...SANDBOX_AGENT_ENV,...this.#e.options.env,HOME:MICROSANDBOX_HOME,...createTransformBrokerEnvironment(createMicrosandboxNetworkPlan(this.#n)),...e.env},n=await this.#i.execStreamWith(`bash`,n=>n.args([`-lc`,e.command]).cwd(e.workingDirectory??WORKSPACE_ROOT).envs(t).user(MICROSANDBOX_USER));return e.abortSignal!==void 0&&e.abortSignal.addEventListener(`abort`,()=>{n.kill().catch(()=>{})},{once:!0}),adaptMicrosandboxExecToSandboxProcess(n)}async stopAndSnapshot(e){await this.#i.stop().catch(()=>{}),await stopAndSnapshotMicrosandboxSandbox(this.#e.module,this.#a,e)}async writeFiles(e){let t=this.#i.fs();for(let n of e){let e=posix.dirname(n.path);await this.runInternalCommand({command:`mkdir -p ${shellQuote(e)}`,user:MICROSANDBOX_USER}),await t.write(n.path,n.content),await this.runInternalCommand({command:`chown ${MICROSANDBOX_USER}:${MICROSANDBOX_USER} ${shellQuote(n.path)}`,user:`root`})}}async writeMetadata(e,t){this.#t=e,this.#r=t,await writeSessionMetadata(e,{image:this.#e.options.image,networkPolicy:this.#n,optionsHash:t,sandboxName:this.#a,stateSnapshotName:this.#o,version:MICROSANDBOX_METADATA_VERSION})}async runInternalCommand(e){if(e.abortSignal?.aborted)throw new DOMException(`The operation was aborted.`,`AbortError`);let t=await this.#i.execWith(`bash`,t=>t.args([`-lc`,e.command]).cwd(WORKSPACE_ROOT).user(e.user));if(t.code!==0){let n=e.failureMessage??`Microsandbox command failed.`;throw Error(`${n} ${t.stderr()}`.trim())}}};async function createPreparedMicrosandbox(e){let t=e.setupBaseRuntime?`allow-all`:e.networkPolicy,n=await createMicrosandbox({fromSnapshot:e.fromSnapshot,log:e.log,module:e.module,name:e.name,networkPolicy:t,options:e.options,resourcesPath:e.resourcesPath,tags:e.tags,user:e.setupBaseRuntime?void 0:MICROSANDBOX_USER,workdir:e.setupBaseRuntime?`/`:WORKSPACE_ROOT}),r=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.name,t);return e.setupBaseRuntime&&(await withProgressHeartbeat(`preparing base runtime inside VM`,e.log,async()=>{await ensureMicrosandboxBaseRuntime(n,{log:e.log})}),e.networkPolicy!==void 0&&e.networkPolicy!==`allow-all`&&(e.log?.(`applying network policy`),await r.setNetworkPolicy(e.networkPolicy))),r}async function connectMicrosandbox(e){let t;try{t=await e.module.Sandbox.get(e.metadata.sandboxName)}catch(t){if(!isMicrosandboxNotFoundError$1(t))throw t;return e.metadata.stateSnapshotName===void 0?null:await restoreMicrosandboxSessionSnapshot(e)}if(t.status!==`running`&&t.status!==`draining`&&e.metadata.stateSnapshotName!==void 0)return await restoreMicrosandboxSessionSnapshot(e);let n=t.status===`running`||t.status===`draining`?await t.connectWithTimeout(1e4):await t.startDetached();return new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,e.metadata.sandboxName,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName)}async function restoreMicrosandboxSessionSnapshot(e){if(e.metadata.stateSnapshotName===void 0||!await snapshotExists$1(e.module,e.metadata.stateSnapshotName))return null;let t=createProviderName(`eve-sbx-ses`,`${e.sessionKey}:${randomUUID()}`),n=await createMicrosandbox({fromSnapshot:e.metadata.stateSnapshotName,module:e.module,name:t,networkPolicy:e.metadata.networkPolicy,options:e.options,tags:e.tags,user:MICROSANDBOX_USER,workdir:WORKSPACE_ROOT});await removeSandboxIfExists(e.module,e.metadata.sandboxName);let r=new MicrosandboxVm({module:e.module,options:e.options,sessionKey:e.sessionKey,tags:e.tags},n,t,e.metadata.networkPolicy,e.metadataPath,e.metadata.optionsHash,e.metadata.stateSnapshotName);return await r.writeMetadata(e.metadataPath,e.metadata.optionsHash),r}const MICROSANDBOX_MISSING_PACKAGE_MESSAGE=`The microsandbox sandbox provider requires the \`microsandbox\` package, which is not bundled with eve. Install it in your application (for example \`pnpm add -D ${MICROSANDBOX_INSTALL_SPECIFIER}\`), or use DockerSandbox or VercelSandbox instead.`;async function loadMicrosandboxModule(e){e.log?.(`checking microsandbox platform support`),await assertMicrosandboxPlatformCandidate();let t=await withProgressHeartbeat(`loading microsandbox npm package`,e.log,()=>e.host.loadOptionalPackage({autoInstall:e.options.setup.autoInstall,importModule:async()=>await import(`microsandbox`),installPackageName:MICROSANDBOX_INSTALL_SPECIFIER,missingMessage:MICROSANDBOX_MISSING_PACKAGE_MESSAGE,packageName:MICROSANDBOX_PACKAGE_NAME}));if(e.log?.(`checking microsandbox VM runtime`),!t.isInstalled()){if(!e.options.setup.autoInstall||!isEveDevEnvironment())throw Error("The microsandbox VM runtime is not installed. Run `npx microsandbox install`, set MSB_PATH for a custom install, or let `eve dev` install it automatically with microsandbox({ setup: { autoInstall: true } }).");await withProgressHeartbeat(`installing microsandbox VM runtime`,e.log,async()=>{await t.setup().skipVerify(e.options.setup.skipVerify).install()})}return e.log?.(`microsandbox runtime ready`),t}async function withProgressHeartbeat(e,t,n){if(t?.(e),t===void 0)return await n();let r=Date.now(),i=setInterval(()=>{t(`${e} (${Math.round((Date.now()-r)/1e3)}s elapsed)`)},1e4);i.unref?.();try{return await n()}finally{clearInterval(i)}}async function loadMicrosandboxWithoutInstall(e){try{let t=await importInstalledEnginePackage({appRoot:e,packageName:MICROSANDBOX_PACKAGE_NAME});return t.isInstalled()?t:null}catch{return null}}async function stopAndSnapshotMicrosandboxSandbox(e,t,n){for(let r=0;r<3;r+=1){let i=await e.Sandbox.get(t);await i.stopWithTimeout(r===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{});try{await i.snapshot(n);return}catch(e){if(!isMicrosandboxSnapshotSourceRunningError(e)||r===2)throw e;await i.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250))}}}function createProviderName(e,t,n=``){return`${e}-${createStableHash(`${t}:${n}`).slice(0,32)}`}function createStableHash(e){return createHash(`sha256`).update(e).digest(`hex`)}async function doesPathExist(e){try{return await access(e),!0}catch{return!1}}async function createMicrosandbox(e){let t=e.module.Sandbox.builder(e.name).cpus(e.options.cpus).detached(!0).envs({...e.options.env,HOME:MICROSANDBOX_HOME}).labels(resolveMicrosandboxLabels(e.tags)).memory(e.options.memoryMiB).pullPolicy(e.options.pullPolicy).replace().workdir(e.workdir);t=e.fromSnapshot===void 0?t.image(e.options.image):t.fromSnapshot(e.fromSnapshot),e.options.image.startsWith(`127.0.0.1:`)&&(t=t.registry(e=>e.insecure())),e.resourcesPath!==void 0&&(t=t.volume(`/eve/resources`,t=>t.bind(e.resourcesPath).readonly())),e.user!==void 0&&(t=t.user(e.user));let n=e.fromSnapshot===void 0?`image "${e.options.image}"`:`snapshot "${e.fromSnapshot}"`;return await createMicrosandboxWithProgress({builder:applyMicrosandboxNetwork(t,e.networkPolicy),errorType:e.module.MicrosandboxError,log:e.log,source:n})}async function removeSandboxIfExists(e,t){for(let n=0;n<3;n+=1)try{let r=await e.Sandbox.get(t);await r.stopWithTimeout(n===0?MICROSANDBOX_STOP_TIMEOUT_MS:0).catch(()=>{}),await r.remove();return}catch(r){if(isMicrosandboxNotFoundError$1(r))return;if(isMicrosandboxStillRunningError(r)&&n<2){await(await e.Sandbox.get(t).catch(()=>null))?.kill().catch(()=>{}),await new Promise(e=>setTimeout(e,250));continue}throw r}}function resolveMicrosandboxLabels(e){return{"eve.provider":`microsandbox`,...withDevelopmentSandboxTags(e)}}export{MicrosandboxVm,connectMicrosandbox,createPreparedMicrosandbox,createProviderName,createStableHash,doesPathExist,isMicrosandboxNotFoundError,loadMicrosandboxModule,loadMicrosandboxWithoutInstall,removeSnapshotIfExists,sandboxExists,snapshotExists,stopAndSnapshotMicrosandboxSandbox};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{isToolSessionId}from"#execution/tool-session/id.js";import{withToolSessionSandboxes}from"#execution/tool-session/sandbox.js";import{streamToBuffer}from"#execution/sandbox/stream-utils.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{VERCEL_EVE_SANDBOX_IMAGE}from"#execution/sandbox/bindings/eve-image.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{buildSandboxSession}from"#execution/sandbox/session.js";import{createSandboxProviderIdentity}from"#execution/sandbox/provider-identity.js";import{isSandboxPreparedArtifactRecord,providerResourceTargetFiles,sandboxProviderResourceIdentity}from"#shared/sandbox-provider.js";import{SandboxTemplateNotProvisionedError}from"#shared/sandbox-template-error.js";import{adaptMultiplexedCommandToSandboxProcess}from"#execution/sandbox/multiplexed-command.js";import{resolveSandboxModelPath}from"#shared/skill-paths.js";import{isVercelSandboxMissingError,isVercelSandboxNameConflictError,isVercelSnapshotNotFoundError,isVercelSnapshotUnavailableError}from"#execution/sandbox/bindings/vercel-errors.js";import{ensureVercelSandboxTags,errorMessage,resolveVercelSandboxTags}from"#execution/sandbox/bindings/vercel-options.js";import{applyInitialVercelNetworkPolicy,createVercelNetworkPolicySetter,ensureVercelSandboxBaseRuntime,withBaseSetupNetworkPolicy}from"#execution/sandbox/bindings/vercel-base-runtime.js";import{createVercelEveImageSandbox}from"#execution/sandbox/bindings/vercel-create-sdk.js";import{withToolSessionRetention}from"#execution/sandbox/bindings/vercel-tool-sessions.js";import{getNamedVercelSandbox}from"#execution/sandbox/bindings/vercel-lookup.js";import{deleteUnusableVercelSandbox,deleteVercelSandbox,stopVercelSandbox}from"#execution/sandbox/bindings/vercel-lifecycle.js";import{normalizeVercelReadStream}from"#execution/sandbox/bindings/vercel-read-stream.js";function createVercelSandboxProvider(e){let{prepare:t,...n}=e??{};return createVercelSandbox({createOptions:n,prepare:t})}function createVercelSandbox(e={}){let t=e.loadSandboxModule??(async()=>await import(`#compiled/@vercel/sandbox/index.js`)),n=e.loadDeleteSandboxModule??(async()=>await import(`#compiled/@vercel/sandbox/index.js`)),r={timeout:DEFAULT_SANDBOX_TIMEOUT_MS,...e.createOptions},i=e.createSandbox??createVercelEveImageSandbox;async function openSession(e,a,o,s){let c=requirePreparedVercelTemplate(o),{mounts:l,...u}=a??{},d=isToolSessionId(e.session.id),f={...r,...u},p=d?withToolSessionRetention(f):f,m=resolveVercelSandboxTags(p.tags,{sessionId:e.session.id}),h=await t(),g={createOptions:p,createSandbox:i,resolveSessionCreateOptions:l===void 0?void 0:async()=>({mounts:l}),sandboxModule:h,sessionKey:s,snapshotId:c.snapshotId,tags:m},_;try{if(_=await ensureSession(g),_=await ensureUsableSession({expired:d?isVercelSnapshotNotFoundError:isVercelSnapshotUnavailableError,input:g,loadDeleteSandboxModule:n,session:_}),_.created&&c.snapshotId===void 0&&u.networkPolicy!==void 0)try{await applyInitialVercelNetworkPolicy(_.sandbox,u.networkPolicy)}catch(t){try{await deleteVercelSandbox({createOptions:p,loadDeleteSandboxModule:n,sandbox:_.sandbox})}catch(n){throw AggregateError([t,n],`Failed to apply network policy and discard Vercel sandbox session "${e.session.id}".`,{cause:t})}throw t}}catch(t){throw isVercelSnapshotUnavailableError(t)&&c.snapshotId!==void 0?new SandboxTemplateNotProvisionedError({providerName:`vercel`,templateKey:c.snapshotId}):Error(`Failed to open Vercel sandbox session "${e.session.id}": ${errorMessage(t)}`,{cause:t})}return createHandle({createOptions:p,loadDeleteSandboxModule:n,sandbox:_.sandbox})}return withToolSessionSandboxes({async prepare(n){let a=providerResourceTargetFiles(n.resources);if(e.skipEmptyPreparation===!0&&e.prepare===void 0&&a.length===0)return{};let o=`eve-sbx-tpl-vercel-${createSandboxProviderIdentity({createOptions:vercelIdentityOptions(r),resolvedImage:r.source===void 0?r.image??VERCEL_EVE_SANDBOX_IMAGE:void 0,resources:sandboxProviderResourceIdentity(n.resources),sourceRevision:n.sourceRevision,version:2}).slice(0,32)}`;try{return{snapshotId:(await ensureTemplateWithUnavailableRetry({createOptions:r,createSandbox:i,loadSandboxModule:t,log:n.log,prepareSandbox:e.prepare,seedFiles:a,templateKey:o})).template.snapshotId}}catch(e){throw Error(`Failed to prepare Vercel sandbox snapshot: ${errorMessage(e)}`,{cause:e})}},async resume(e,i,a){requirePreparedVercelTemplate(i);let o=requireVercelSessionState(a),s=await t(),c=await getNamedVercelSandbox({createOptions:r,sandboxModule:s,sandboxName:o.sandboxName});if(c===null)throw Error(`Vercel sandbox session "${o.sandboxName}" no longer exists.`);return await ensureVercelSandboxBaseRuntime(c),createHandle({createOptions:r,loadDeleteSandboxModule:n,sandbox:c})},async start(e,t,n){let i=vercelSessionName(e.session.id,t,n,r);return{handle:await openSession(e,t,n,i),state:{sandboxName:i,version:3}}}})}function vercelSessionName(e,t,n,r){let i=requirePreparedVercelTemplate(n);return`eve-sbx-vercel-${createSandboxProviderIdentity({artifact:i,createOptions:vercelIdentityOptions(r),options:vercelIdentityOptions(t),sessionId:e,version:1}).slice(0,32)}`}function vercelIdentityOptions(e){if(e===void 0)return;let t=new Set([`fetch`,`projectId`,`signal`,`teamId`,`token`]);return Object.fromEntries(Object.entries(e).filter(([e])=>!t.has(e)))}function requireVercelSessionState(e){if(!isSandboxPreparedArtifactRecord(e)||e.version!==3||typeof e.sandboxName!=`string`)throw Error(`Invalid Vercel sandbox session state.`);return{sandboxName:e.sandboxName,version:3}}function requirePreparedVercelTemplate(e){if(!isSandboxPreparedArtifactRecord(e)||e.snapshotId!==void 0&&typeof e.snapshotId!=`string`)throw Error(`Invalid prepared Vercel sandbox artifact.`);return e.snapshotId===void 0?{}:{snapshotId:e.snapshotId}}async function ensureTemplateWithUnavailableRetry(e){try{return await ensureTemplate(e)}catch(t){if(!isVercelSnapshotUnavailableError(t)&&!isVercelSandboxMissingError(t))throw t;return e.log?.(`cached template disappeared; rebuilding sandbox template`),await ensureTemplate(e)}}async function ensureTemplate(e){let t=await e.loadSandboxModule(),n=await getNamedVercelSandbox({createOptions:e.createOptions,sandboxModule:t,sandboxName:e.templateKey}),r=resolveVercelSandboxTags(e.createOptions.tags,e.tags),i=extractAuthorSnapshotId(e.createOptions);n!==null&&isUnprovisionedTerminalTemplateSandbox(n,i)&&(await n.delete(),n=null),n===null?n=await e.createSandbox({sandboxModule:t,createOptions:withBaseSetupNetworkPolicy({...e.createOptions,name:e.templateKey,persistent:!0,tags:r})}):await ensureVercelSandboxTags(n,r);let a=typeof n.currentSnapshotId==`string`&&n.currentSnapshotId.length>0&&n.currentSnapshotId!==i?n.currentSnapshotId:null;if(a!==null)return{template:{sandboxName:n.name,snapshotId:a,templateKey:e.templateKey}};e.log?.(`preparing base runtime inside sandbox`),await ensureVercelSandboxBaseRuntime(n),await applyInitialVercelNetworkPolicy(n,e.createOptions.networkPolicy);let o=buildSandboxSession(createVercelInternalSandboxSession(n),createVercelNetworkPolicySetter(n));await writeVercelSandboxSeedFiles({sandbox:n,seedFiles:e.seedFiles,session:o}),e.log?.(`running sandbox preparation`),await e.prepareSandbox?.(createLoggingSandboxSession({log:e.log,session:o}));let s=await n.snapshot();return{template:{sandboxName:n.name,snapshotId:s.snapshotId,templateKey:e.templateKey}}}async function ensureUsableSession(e){try{return await ensureVercelSandboxBaseRuntime(e.session.sandbox),e.session}catch(t){if(e.session.created||!e.expired(t))throw t}try{await deleteUnusableVercelSandbox({createOptions:e.input.createOptions,loadDeleteSandboxModule:e.loadDeleteSandboxModule,sandbox:e.session.sandbox})}catch(e){if(!isVercelSandboxMissingError(e))throw e}let t=await ensureSession(e.input);return await ensureVercelSandboxBaseRuntime(t.sandbox),t}async function ensureSession(e){let t=e.sessionKey,n=await getNamedVercelSandbox({createOptions:e.createOptions,sandboxModule:e.sandboxModule,sandboxName:t});if(n!==null)return await ensureVercelSandboxTags(n,e.tags),{created:!1,sandbox:n};let r=createSessionCreateParams(e,t,await e.resolveSessionCreateOptions?.());e.tags!==void 0&&(r.tags=e.tags);try{return{created:!0,sandbox:await e.createSandbox({createOptions:r,sandboxModule:e.sandboxModule})}}catch(n){if(!isVercelSandboxNameConflictError(n))throw n;let r=await getNamedVercelSandbox({...e,sandboxName:t});if(r===null)throw n;return{created:!1,sandbox:r}}}function createSessionCreateParams(e,t,n={}){let r={...e.createOptions,...n};if(e.snapshotId===void 0)return withBaseSetupNetworkPolicy({...r,name:t,persistent:!0});let{image:i,runtime:a,source:o,...s}=r;return{...s,name:t,persistent:!0,source:{snapshotId:e.snapshotId,type:`snapshot`}}}function createHandle(e){let{sandbox:t}=e;return{sandbox:buildSandboxSession(createVercelInternalSandboxSession(t),createVercelNetworkPolicySetter(t)),async onSandboxDelete(n){await deleteVercelSandbox({createOptions:e.createOptions,loadDeleteSandboxModule:e.loadDeleteSandboxModule,sandbox:t,signal:n?.abortSignal})},async onSandboxStop(){await stopVercelSandbox(t)},async onRuntimeShutdown(){try{await stopVercelSandbox(t)}catch{}}}}function createVercelInternalSandboxSession(e){return{resolvePath:resolveVercelSandboxPath,async spawn(t){let n=await e.runCommand({args:[`-lc`,t.command],cmd:`bash`,cwd:t.workingDirectory??WORKSPACE_ROOT,detached:!0,env:t.env,signal:t.abortSignal});return adaptMultiplexedCommandToSandboxProcess({command:n,getOutput:e=>e.stream})},async readFile(t){return normalizeVercelReadStream(await e.readFile({path:t.path}))},async writeFile(t){let n=await streamToBuffer(t.content),r=await resolveVercelWritePath(e,t.path,t.abortSignal);await e.writeFiles([{content:n,path:r}],{signal:t.abortSignal})},async removePath(t){await e.fs.rm(t.path,{force:t.force,recursive:t.recursive,signal:t.abortSignal})}}}async function writeVercelSandboxSeedFiles(e){if(e.seedFiles.length===0)return;let t=await Promise.all(e.seedFiles.map(async t=>({content:typeof t.content==`string`?Buffer.from(t.content):t.content,path:await resolveSandboxModelPath({path:t.path,sandbox:e.session})})));await e.sandbox.writeFiles(t)}function resolveVercelSandboxPath(e){return e.startsWith(`/`)?e:`${WORKSPACE_ROOT}/${e}`}async function resolveVercelWritePath(e,t,n){let r=await e.runCommand({args:[`-m`,`--`,t],cmd:`realpath`,signal:n}),i=(await r.stdout()).trim();if(r.exitCode!==0||!i.startsWith(`/`)||i.includes(`
|
|
1
|
+
import{isToolSessionId}from"#execution/tool-session/id.js";import{withToolSessionSandboxes}from"#execution/tool-session/sandbox.js";import{streamToBuffer}from"#execution/sandbox/stream-utils.js";import{WORKSPACE_ROOT}from"#runtime/workspace/types.js";import{SANDBOX_AGENT_ENV,buildSandboxSession}from"#execution/sandbox/session.js";import{VERCEL_EVE_SANDBOX_IMAGE}from"#execution/sandbox/bindings/eve-image.js";import{createLoggingSandboxSession}from"#execution/sandbox/logging-session.js";import{createSandboxProviderIdentity}from"#execution/sandbox/provider-identity.js";import{isSandboxPreparedArtifactRecord,providerResourceTargetFiles,sandboxProviderResourceIdentity}from"#shared/sandbox-provider.js";import{SandboxTemplateNotProvisionedError}from"#shared/sandbox-template-error.js";import{adaptMultiplexedCommandToSandboxProcess}from"#execution/sandbox/multiplexed-command.js";import{resolveSandboxModelPath}from"#shared/skill-paths.js";import{isVercelSandboxMissingError,isVercelSandboxNameConflictError,isVercelSnapshotNotFoundError,isVercelSnapshotUnavailableError}from"#execution/sandbox/bindings/vercel-errors.js";import{ensureVercelSandboxTags,errorMessage,resolveVercelSandboxTags}from"#execution/sandbox/bindings/vercel-options.js";import{applyInitialVercelNetworkPolicy,createVercelNetworkPolicySetter,ensureVercelSandboxBaseRuntime,withBaseSetupNetworkPolicy}from"#execution/sandbox/bindings/vercel-base-runtime.js";import{createVercelEveImageSandbox}from"#execution/sandbox/bindings/vercel-create-sdk.js";import{withToolSessionRetention}from"#execution/sandbox/bindings/vercel-tool-sessions.js";import{getNamedVercelSandbox}from"#execution/sandbox/bindings/vercel-lookup.js";import{deleteUnusableVercelSandbox,deleteVercelSandbox,stopVercelSandbox}from"#execution/sandbox/bindings/vercel-lifecycle.js";import{normalizeVercelReadStream}from"#execution/sandbox/bindings/vercel-read-stream.js";function createVercelSandboxProvider(e){let{prepare:t,...n}=e??{};return createVercelSandbox({createOptions:n,prepare:t})}function createVercelSandbox(e={}){let t=e.loadSandboxModule??(async()=>await import(`#compiled/@vercel/sandbox/index.js`)),n=e.loadDeleteSandboxModule??(async()=>await import(`#compiled/@vercel/sandbox/index.js`)),r={timeout:DEFAULT_SANDBOX_TIMEOUT_MS,...e.createOptions},i=e.createSandbox??createVercelEveImageSandbox;async function openSession(e,a,o,s){let c=requirePreparedVercelTemplate(o),{mounts:l,...u}=a??{},d=isToolSessionId(e.session.id),f={...r,...u},p=d?withToolSessionRetention(f):f,m=resolveVercelSandboxTags(p.tags,{sessionId:e.session.id}),h=await t(),g={createOptions:p,createSandbox:i,resolveSessionCreateOptions:l===void 0?void 0:async()=>({mounts:l}),sandboxModule:h,sessionKey:s,snapshotId:c.snapshotId,tags:m},_;try{if(_=await ensureSession(g),_=await ensureUsableSession({expired:d?isVercelSnapshotNotFoundError:isVercelSnapshotUnavailableError,input:g,loadDeleteSandboxModule:n,session:_}),_.created&&c.snapshotId===void 0&&u.networkPolicy!==void 0)try{await applyInitialVercelNetworkPolicy(_.sandbox,u.networkPolicy)}catch(t){try{await deleteVercelSandbox({createOptions:p,loadDeleteSandboxModule:n,sandbox:_.sandbox})}catch(n){throw AggregateError([t,n],`Failed to apply network policy and discard Vercel sandbox session "${e.session.id}".`,{cause:t})}throw t}}catch(t){throw isVercelSnapshotUnavailableError(t)&&c.snapshotId!==void 0?new SandboxTemplateNotProvisionedError({providerName:`vercel`,templateKey:c.snapshotId}):Error(`Failed to open Vercel sandbox session "${e.session.id}": ${errorMessage(t)}`,{cause:t})}return createHandle({createOptions:p,loadDeleteSandboxModule:n,sandbox:_.sandbox})}return withToolSessionSandboxes({async prepare(n){let a=providerResourceTargetFiles(n.resources);if(e.skipEmptyPreparation===!0&&e.prepare===void 0&&a.length===0)return{};let o=`eve-sbx-tpl-vercel-${createSandboxProviderIdentity({createOptions:vercelIdentityOptions(r),resolvedImage:r.source===void 0?r.image??VERCEL_EVE_SANDBOX_IMAGE:void 0,resources:sandboxProviderResourceIdentity(n.resources),sourceRevision:n.sourceRevision,version:2}).slice(0,32)}`;try{return{snapshotId:(await ensureTemplateWithUnavailableRetry({createOptions:r,createSandbox:i,loadSandboxModule:t,log:n.log,prepareSandbox:e.prepare,seedFiles:a,templateKey:o})).template.snapshotId}}catch(e){throw Error(`Failed to prepare Vercel sandbox snapshot: ${errorMessage(e)}`,{cause:e})}},async resume(e,i,a){requirePreparedVercelTemplate(i);let o=requireVercelSessionState(a),s=await t(),c=await getNamedVercelSandbox({createOptions:r,sandboxModule:s,sandboxName:o.sandboxName});if(c===null)throw Error(`Vercel sandbox session "${o.sandboxName}" no longer exists.`);return await ensureVercelSandboxBaseRuntime(c),createHandle({createOptions:r,loadDeleteSandboxModule:n,sandbox:c})},async start(e,t,n){let i=vercelSessionName(e.session.id,t,n,r);return{handle:await openSession(e,t,n,i),state:{sandboxName:i,version:3}}}})}function vercelSessionName(e,t,n,r){let i=requirePreparedVercelTemplate(n);return`eve-sbx-vercel-${createSandboxProviderIdentity({artifact:i,createOptions:vercelIdentityOptions(r),options:vercelIdentityOptions(t),sessionId:e,version:1}).slice(0,32)}`}function vercelIdentityOptions(e){if(e===void 0)return;let t=new Set([`fetch`,`projectId`,`signal`,`teamId`,`token`]);return Object.fromEntries(Object.entries(e).filter(([e])=>!t.has(e)))}function requireVercelSessionState(e){if(!isSandboxPreparedArtifactRecord(e)||e.version!==3||typeof e.sandboxName!=`string`)throw Error(`Invalid Vercel sandbox session state.`);return{sandboxName:e.sandboxName,version:3}}function requirePreparedVercelTemplate(e){if(!isSandboxPreparedArtifactRecord(e)||e.snapshotId!==void 0&&typeof e.snapshotId!=`string`)throw Error(`Invalid prepared Vercel sandbox artifact.`);return e.snapshotId===void 0?{}:{snapshotId:e.snapshotId}}async function ensureTemplateWithUnavailableRetry(e){try{return await ensureTemplate(e)}catch(t){if(!isVercelSnapshotUnavailableError(t)&&!isVercelSandboxMissingError(t))throw t;return e.log?.(`cached template disappeared; rebuilding sandbox template`),await ensureTemplate(e)}}async function ensureTemplate(e){let t=await e.loadSandboxModule(),n=await getNamedVercelSandbox({createOptions:e.createOptions,sandboxModule:t,sandboxName:e.templateKey}),r=resolveVercelSandboxTags(e.createOptions.tags,e.tags),i=extractAuthorSnapshotId(e.createOptions);n!==null&&isUnprovisionedTerminalTemplateSandbox(n,i)&&(await n.delete(),n=null),n===null?n=await e.createSandbox({sandboxModule:t,createOptions:withBaseSetupNetworkPolicy({...e.createOptions,name:e.templateKey,persistent:!0,tags:r})}):await ensureVercelSandboxTags(n,r);let a=typeof n.currentSnapshotId==`string`&&n.currentSnapshotId.length>0&&n.currentSnapshotId!==i?n.currentSnapshotId:null;if(a!==null)return{template:{sandboxName:n.name,snapshotId:a,templateKey:e.templateKey}};e.log?.(`preparing base runtime inside sandbox`),await ensureVercelSandboxBaseRuntime(n),await applyInitialVercelNetworkPolicy(n,e.createOptions.networkPolicy);let o=buildSandboxSession(createVercelInternalSandboxSession(n,e.createOptions.env),createVercelNetworkPolicySetter(n));await writeVercelSandboxSeedFiles({sandbox:n,seedFiles:e.seedFiles,session:o}),e.log?.(`running sandbox preparation`),await e.prepareSandbox?.(createLoggingSandboxSession({log:e.log,session:o}));let s=await n.snapshot();return{template:{sandboxName:n.name,snapshotId:s.snapshotId,templateKey:e.templateKey}}}async function ensureUsableSession(e){try{return await ensureVercelSandboxBaseRuntime(e.session.sandbox),e.session}catch(t){if(e.session.created||!e.expired(t))throw t}try{await deleteUnusableVercelSandbox({createOptions:e.input.createOptions,loadDeleteSandboxModule:e.loadDeleteSandboxModule,sandbox:e.session.sandbox})}catch(e){if(!isVercelSandboxMissingError(e))throw e}let t=await ensureSession(e.input);return await ensureVercelSandboxBaseRuntime(t.sandbox),t}async function ensureSession(e){let t=e.sessionKey,n=await getNamedVercelSandbox({createOptions:e.createOptions,sandboxModule:e.sandboxModule,sandboxName:t});if(n!==null)return await ensureVercelSandboxTags(n,e.tags),{created:!1,sandbox:n};let r=createSessionCreateParams(e,t,await e.resolveSessionCreateOptions?.());e.tags!==void 0&&(r.tags=e.tags);try{return{created:!0,sandbox:await e.createSandbox({createOptions:r,sandboxModule:e.sandboxModule})}}catch(n){if(!isVercelSandboxNameConflictError(n))throw n;let r=await getNamedVercelSandbox({...e,sandboxName:t});if(r===null)throw n;return{created:!1,sandbox:r}}}function createSessionCreateParams(e,t,n={}){let r={...e.createOptions,...n};if(e.snapshotId===void 0)return withBaseSetupNetworkPolicy({...r,name:t,persistent:!0});let{image:i,runtime:a,source:o,...s}=r;return{...s,name:t,persistent:!0,source:{snapshotId:e.snapshotId,type:`snapshot`}}}function createHandle(e){let{sandbox:t}=e;return{sandbox:buildSandboxSession(createVercelInternalSandboxSession(t,e.createOptions.env),createVercelNetworkPolicySetter(t)),async onSandboxDelete(n){await deleteVercelSandbox({createOptions:e.createOptions,loadDeleteSandboxModule:e.loadDeleteSandboxModule,sandbox:t,signal:n?.abortSignal})},async onSandboxStop(){await stopVercelSandbox(t)},async onRuntimeShutdown(){try{await stopVercelSandbox(t)}catch{}}}}function createVercelInternalSandboxSession(e,t){let n={...SANDBOX_AGENT_ENV,...t};return{resolvePath:resolveVercelSandboxPath,async spawn(t){let r=await e.runCommand({args:[`-lc`,t.command],cmd:`bash`,cwd:t.workingDirectory??WORKSPACE_ROOT,detached:!0,env:{...n,...t.env},signal:t.abortSignal});return adaptMultiplexedCommandToSandboxProcess({command:r,getOutput:e=>e.stream})},async readFile(t){return normalizeVercelReadStream(await e.readFile({path:t.path}))},async writeFile(t){let n=await streamToBuffer(t.content),r=await resolveVercelWritePath(e,t.path,t.abortSignal);await e.writeFiles([{content:n,path:r}],{signal:t.abortSignal})},async removePath(t){await e.fs.rm(t.path,{force:t.force,recursive:t.recursive,signal:t.abortSignal})}}}async function writeVercelSandboxSeedFiles(e){if(e.seedFiles.length===0)return;let t=await Promise.all(e.seedFiles.map(async t=>({content:typeof t.content==`string`?Buffer.from(t.content):t.content,path:await resolveSandboxModelPath({path:t.path,sandbox:e.session})})));await e.sandbox.writeFiles(t)}function resolveVercelSandboxPath(e){return e.startsWith(`/`)?e:`${WORKSPACE_ROOT}/${e}`}async function resolveVercelWritePath(e,t,n){let r=await e.runCommand({args:[`-m`,`--`,t],cmd:`realpath`,signal:n}),i=(await r.stdout()).trim();if(r.exitCode!==0||!i.startsWith(`/`)||i.includes(`
|
|
2
2
|
`))throw Error(`Failed to resolve Vercel Sandbox write path: ${t}`);return i}function isUnprovisionedTerminalTemplateSandbox(e,t){let n=e.currentSnapshotId;return typeof n==`string`&&n.length>0&&n!==t?!1:e.status===`aborted`||e.status===`failed`||e.status===`stopped`}function extractAuthorSnapshotId(e){let t=e.source;if(t?.type===`snapshot`&&typeof t.snapshotId==`string`)return t.snapshotId}const DEFAULT_SANDBOX_TIMEOUT_MS=18e5;export{createVercelSandbox,createVercelSandboxProvider};
|