@truefoundry/trueforge-core 0.0.0 → 0.1.0-rc.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/LICENSE +21 -0
- package/dist/agent-session/ITurnResourceResolver.d.ts +69 -0
- package/dist/agent-session/ITurnResourceResolver.d.ts.map +1 -0
- package/dist/agent-session/ITurnResourceResolver.js +19 -0
- package/dist/agent-session/ITurnResourceResolver.js.map +1 -0
- package/dist/agent-session/ITurnResourceResolver.mjs +1 -0
- package/dist/agent-session/ITurnResourceResolver.mjs.map +1 -0
- package/dist/agent-session/SessionHandle.d.ts +81 -0
- package/dist/agent-session/SessionHandle.d.ts.map +1 -0
- package/dist/agent-session/SessionHandle.js +392 -0
- package/dist/agent-session/SessionHandle.js.map +1 -0
- package/dist/agent-session/SessionHandle.mjs +371 -0
- package/dist/agent-session/SessionHandle.mjs.map +1 -0
- package/dist/agent-session/Sessions.d.ts +25 -0
- package/dist/agent-session/Sessions.d.ts.map +1 -0
- package/dist/agent-session/Sessions.js +71 -0
- package/dist/agent-session/Sessions.js.map +1 -0
- package/dist/agent-session/Sessions.mjs +46 -0
- package/dist/agent-session/Sessions.mjs.map +1 -0
- package/dist/agent-session/TurnHandle.d.ts +88 -0
- package/dist/agent-session/TurnHandle.d.ts.map +1 -0
- package/dist/agent-session/TurnHandle.js +490 -0
- package/dist/agent-session/TurnHandle.js.map +1 -0
- package/dist/agent-session/TurnHandle.mjs +469 -0
- package/dist/agent-session/TurnHandle.mjs.map +1 -0
- package/dist/agent-session/TurnResourceResolver.d.ts +154 -0
- package/dist/agent-session/TurnResourceResolver.d.ts.map +1 -0
- package/dist/agent-session/TurnResourceResolver.js +178 -0
- package/dist/agent-session/TurnResourceResolver.js.map +1 -0
- package/dist/agent-session/TurnResourceResolver.mjs +153 -0
- package/dist/agent-session/TurnResourceResolver.mjs.map +1 -0
- package/dist/agent-session/builtinsFromSpec.d.ts +19 -0
- package/dist/agent-session/builtinsFromSpec.d.ts.map +1 -0
- package/dist/agent-session/builtinsFromSpec.js +73 -0
- package/dist/agent-session/builtinsFromSpec.js.map +1 -0
- package/dist/agent-session/builtinsFromSpec.mjs +48 -0
- package/dist/agent-session/builtinsFromSpec.mjs.map +1 -0
- package/dist/agent-session/index.d.ts +29 -0
- package/dist/agent-session/index.d.ts.map +1 -0
- package/dist/agent-session/index.js +117 -0
- package/dist/agent-session/index.js.map +1 -0
- package/dist/agent-session/index.mjs +84 -0
- package/dist/agent-session/index.mjs.map +1 -0
- package/dist/agent-session/models/SessionRecord.d.ts +34 -0
- package/dist/agent-session/models/SessionRecord.d.ts.map +1 -0
- package/dist/agent-session/models/SessionRecord.js +19 -0
- package/dist/agent-session/models/SessionRecord.js.map +1 -0
- package/dist/agent-session/models/SessionRecord.mjs +1 -0
- package/dist/agent-session/models/SessionRecord.mjs.map +1 -0
- package/dist/agent-session/models/TurnRecord.d.ts +37 -0
- package/dist/agent-session/models/TurnRecord.d.ts.map +1 -0
- package/dist/agent-session/models/TurnRecord.js +31 -0
- package/dist/agent-session/models/TurnRecord.js.map +1 -0
- package/dist/agent-session/models/TurnRecord.mjs +6 -0
- package/dist/agent-session/models/TurnRecord.mjs.map +1 -0
- package/dist/agent-session/schemas/agentSpec.d.ts +142 -0
- package/dist/agent-session/schemas/agentSpec.d.ts.map +1 -0
- package/dist/agent-session/schemas/agentSpec.js +170 -0
- package/dist/agent-session/schemas/agentSpec.js.map +1 -0
- package/dist/agent-session/schemas/agentSpec.mjs +154 -0
- package/dist/agent-session/schemas/agentSpec.mjs.map +1 -0
- package/dist/agent-session/schemas/events.d.ts +1037 -0
- package/dist/agent-session/schemas/events.d.ts.map +1 -0
- package/dist/agent-session/schemas/events.js +80 -0
- package/dist/agent-session/schemas/events.js.map +1 -0
- package/dist/agent-session/schemas/events.mjs +69 -0
- package/dist/agent-session/schemas/events.mjs.map +1 -0
- package/dist/agent-session/schemas/pagination.d.ts +9 -0
- package/dist/agent-session/schemas/pagination.d.ts.map +1 -0
- package/dist/agent-session/schemas/pagination.js +36 -0
- package/dist/agent-session/schemas/pagination.js.map +1 -0
- package/dist/agent-session/schemas/pagination.mjs +11 -0
- package/dist/agent-session/schemas/pagination.mjs.map +1 -0
- package/dist/agent-session/schemas/session.d.ts +319 -0
- package/dist/agent-session/schemas/session.d.ts.map +1 -0
- package/dist/agent-session/schemas/session.js +58 -0
- package/dist/agent-session/schemas/session.js.map +1 -0
- package/dist/agent-session/schemas/session.mjs +30 -0
- package/dist/agent-session/schemas/session.mjs.map +1 -0
- package/dist/agent-session/schemas/turn.d.ts +494 -0
- package/dist/agent-session/schemas/turn.d.ts.map +1 -0
- package/dist/agent-session/schemas/turn.js +131 -0
- package/dist/agent-session/schemas/turn.js.map +1 -0
- package/dist/agent-session/schemas/turn.mjs +102 -0
- package/dist/agent-session/schemas/turn.mjs.map +1 -0
- package/dist/agent-session/store/ISessionStore.d.ts +310 -0
- package/dist/agent-session/store/ISessionStore.d.ts.map +1 -0
- package/dist/agent-session/store/ISessionStore.js +19 -0
- package/dist/agent-session/store/ISessionStore.js.map +1 -0
- package/dist/agent-session/store/ISessionStore.mjs +1 -0
- package/dist/agent-session/store/ISessionStore.mjs.map +1 -0
- package/dist/agent-session/store/InMemorySessionStore.d.ts +55 -0
- package/dist/agent-session/store/InMemorySessionStore.d.ts.map +1 -0
- package/dist/agent-session/store/InMemorySessionStore.js +475 -0
- package/dist/agent-session/store/InMemorySessionStore.js.map +1 -0
- package/dist/agent-session/store/InMemorySessionStore.mjs +461 -0
- package/dist/agent-session/store/InMemorySessionStore.mjs.map +1 -0
- package/dist/agent-session/store/OffsetPageToken.d.ts +13 -0
- package/dist/agent-session/store/OffsetPageToken.d.ts.map +1 -0
- package/dist/agent-session/store/OffsetPageToken.js +60 -0
- package/dist/agent-session/store/OffsetPageToken.js.map +1 -0
- package/dist/agent-session/store/OffsetPageToken.mjs +32 -0
- package/dist/agent-session/store/OffsetPageToken.mjs.map +1 -0
- package/dist/agent-session/store/PageToken.d.ts +4 -0
- package/dist/agent-session/store/PageToken.d.ts.map +1 -0
- package/dist/agent-session/store/PageToken.js +45 -0
- package/dist/agent-session/store/PageToken.js.map +1 -0
- package/dist/agent-session/store/PageToken.mjs +19 -0
- package/dist/agent-session/store/PageToken.mjs.map +1 -0
- package/dist/agent-session/store/SessionEventPageToken.d.ts +14 -0
- package/dist/agent-session/store/SessionEventPageToken.d.ts.map +1 -0
- package/dist/agent-session/store/SessionEventPageToken.js +70 -0
- package/dist/agent-session/store/SessionEventPageToken.js.map +1 -0
- package/dist/agent-session/store/SessionEventPageToken.mjs +42 -0
- package/dist/agent-session/store/SessionEventPageToken.mjs.map +1 -0
- package/dist/agent-session/store/SessionListPageToken.d.ts +24 -0
- package/dist/agent-session/store/SessionListPageToken.d.ts.map +1 -0
- package/dist/agent-session/store/SessionListPageToken.js +66 -0
- package/dist/agent-session/store/SessionListPageToken.js.map +1 -0
- package/dist/agent-session/store/SessionListPageToken.mjs +38 -0
- package/dist/agent-session/store/SessionListPageToken.mjs.map +1 -0
- package/dist/agent-session/store/SessionStoreErrors.d.ts +43 -0
- package/dist/agent-session/store/SessionStoreErrors.d.ts.map +1 -0
- package/dist/agent-session/store/SessionStoreErrors.js +126 -0
- package/dist/agent-session/store/SessionStoreErrors.js.map +1 -0
- package/dist/agent-session/store/SessionStoreErrors.mjs +92 -0
- package/dist/agent-session/store/SessionStoreErrors.mjs.map +1 -0
- package/dist/agent-session/store/assertCreateTurnThreadDelta.d.ts +18 -0
- package/dist/agent-session/store/assertCreateTurnThreadDelta.d.ts.map +1 -0
- package/dist/agent-session/store/assertCreateTurnThreadDelta.js +67 -0
- package/dist/agent-session/store/assertCreateTurnThreadDelta.js.map +1 -0
- package/dist/agent-session/store/assertCreateTurnThreadDelta.mjs +42 -0
- package/dist/agent-session/store/assertCreateTurnThreadDelta.mjs.map +1 -0
- package/dist/core/InstructionBuilder.d.ts +71 -0
- package/dist/core/InstructionBuilder.d.ts.map +1 -0
- package/dist/core/InstructionBuilder.js +95 -0
- package/dist/core/InstructionBuilder.js.map +1 -0
- package/dist/core/InstructionBuilder.mjs +69 -0
- package/dist/core/InstructionBuilder.mjs.map +1 -0
- package/dist/core/capabilities/AgentCapability.d.ts +32 -0
- package/dist/core/capabilities/AgentCapability.d.ts.map +1 -0
- package/dist/core/capabilities/AgentCapability.js +19 -0
- package/dist/core/capabilities/AgentCapability.js.map +1 -0
- package/dist/core/capabilities/AgentCapability.mjs +1 -0
- package/dist/core/capabilities/AgentCapability.mjs.map +1 -0
- package/dist/core/capabilities/AgentContextProcessor.d.ts +30 -0
- package/dist/core/capabilities/AgentContextProcessor.d.ts.map +1 -0
- package/dist/core/capabilities/AgentContextProcessor.js +19 -0
- package/dist/core/capabilities/AgentContextProcessor.js.map +1 -0
- package/dist/core/capabilities/AgentContextProcessor.mjs +1 -0
- package/dist/core/capabilities/AgentContextProcessor.mjs.map +1 -0
- package/dist/core/capabilities/ToolResponseProcessor.d.ts +12 -0
- package/dist/core/capabilities/ToolResponseProcessor.d.ts.map +1 -0
- package/dist/core/capabilities/ToolResponseProcessor.js +19 -0
- package/dist/core/capabilities/ToolResponseProcessor.js.map +1 -0
- package/dist/core/capabilities/ToolResponseProcessor.mjs +1 -0
- package/dist/core/capabilities/ToolResponseProcessor.mjs.map +1 -0
- package/dist/core/capabilities/builtins/AskUserQuestion.d.ts +11 -0
- package/dist/core/capabilities/builtins/AskUserQuestion.d.ts.map +1 -0
- package/dist/core/capabilities/builtins/AskUserQuestion.js +90 -0
- package/dist/core/capabilities/builtins/AskUserQuestion.js.map +1 -0
- package/dist/core/capabilities/builtins/AskUserQuestion.mjs +64 -0
- package/dist/core/capabilities/builtins/AskUserQuestion.mjs.map +1 -0
- package/dist/core/capabilities/builtins/ContextCompaction.d.ts +23 -0
- package/dist/core/capabilities/builtins/ContextCompaction.d.ts.map +1 -0
- package/dist/core/capabilities/builtins/ContextCompaction.js +235 -0
- package/dist/core/capabilities/builtins/ContextCompaction.js.map +1 -0
- package/dist/core/capabilities/builtins/ContextCompaction.mjs +208 -0
- package/dist/core/capabilities/builtins/ContextCompaction.mjs.map +1 -0
- package/dist/core/capabilities/builtins/CurrentDateTime.d.ts +17 -0
- package/dist/core/capabilities/builtins/CurrentDateTime.d.ts.map +1 -0
- package/dist/core/capabilities/builtins/CurrentDateTime.js +75 -0
- package/dist/core/capabilities/builtins/CurrentDateTime.js.map +1 -0
- package/dist/core/capabilities/builtins/CurrentDateTime.mjs +47 -0
- package/dist/core/capabilities/builtins/CurrentDateTime.mjs.map +1 -0
- package/dist/core/capabilities/builtins/DynamicSubAgents.d.ts +39 -0
- package/dist/core/capabilities/builtins/DynamicSubAgents.d.ts.map +1 -0
- package/dist/core/capabilities/builtins/DynamicSubAgents.js +176 -0
- package/dist/core/capabilities/builtins/DynamicSubAgents.js.map +1 -0
- package/dist/core/capabilities/builtins/DynamicSubAgents.mjs +134 -0
- package/dist/core/capabilities/builtins/DynamicSubAgents.mjs.map +1 -0
- package/dist/core/capabilities/builtins/LargeToolResponse.d.ts +40 -0
- package/dist/core/capabilities/builtins/LargeToolResponse.d.ts.map +1 -0
- package/dist/core/capabilities/builtins/LargeToolResponse.js +225 -0
- package/dist/core/capabilities/builtins/LargeToolResponse.js.map +1 -0
- package/dist/core/capabilities/builtins/LargeToolResponse.mjs +186 -0
- package/dist/core/capabilities/builtins/LargeToolResponse.mjs.map +1 -0
- package/dist/core/capabilities/builtins/OpenUI.d.ts +31 -0
- package/dist/core/capabilities/builtins/OpenUI.d.ts.map +1 -0
- package/dist/core/capabilities/builtins/OpenUI.js +376 -0
- package/dist/core/capabilities/builtins/OpenUI.js.map +1 -0
- package/dist/core/capabilities/builtins/OpenUI.mjs +326 -0
- package/dist/core/capabilities/builtins/OpenUI.mjs.map +1 -0
- package/dist/core/errors.d.ts +33 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +88 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/errors.mjs +57 -0
- package/dist/core/errors.mjs.map +1 -0
- package/dist/core/events/PassthroughEvents.d.ts +30 -0
- package/dist/core/events/PassthroughEvents.d.ts.map +1 -0
- package/dist/core/events/PassthroughEvents.js +19 -0
- package/dist/core/events/PassthroughEvents.js.map +1 -0
- package/dist/core/events/PassthroughEvents.mjs +1 -0
- package/dist/core/events/PassthroughEvents.mjs.map +1 -0
- package/dist/core/events/schema.d.ts +1103 -0
- package/dist/core/events/schema.d.ts.map +1 -0
- package/dist/core/events/schema.js +337 -0
- package/dist/core/events/schema.js.map +1 -0
- package/dist/core/events/schema.mjs +283 -0
- package/dist/core/events/schema.mjs.map +1 -0
- package/dist/core/index.d.ts +60 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +209 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +144 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/core/llm/ILLM.d.ts +15 -0
- package/dist/core/llm/ILLM.d.ts.map +1 -0
- package/dist/core/llm/ILLM.js +19 -0
- package/dist/core/llm/ILLM.js.map +1 -0
- package/dist/core/llm/ILLM.mjs +1 -0
- package/dist/core/llm/ILLM.mjs.map +1 -0
- package/dist/core/llm/LLMTypes.d.ts +369 -0
- package/dist/core/llm/LLMTypes.d.ts.map +1 -0
- package/dist/core/llm/LLMTypes.js +170 -0
- package/dist/core/llm/LLMTypes.js.map +1 -0
- package/dist/core/llm/LLMTypes.mjs +133 -0
- package/dist/core/llm/LLMTypes.mjs.map +1 -0
- package/dist/core/llm/VercelAILLM.d.ts +228 -0
- package/dist/core/llm/VercelAILLM.d.ts.map +1 -0
- package/dist/core/llm/VercelAILLM.js +1042 -0
- package/dist/core/llm/VercelAILLM.js.map +1 -0
- package/dist/core/llm/VercelAILLM.mjs +999 -0
- package/dist/core/llm/VercelAILLM.mjs.map +1 -0
- package/dist/core/llm/openaiSchemas.d.ts +190 -0
- package/dist/core/llm/openaiSchemas.d.ts.map +1 -0
- package/dist/core/llm/openaiSchemas.js +144 -0
- package/dist/core/llm/openaiSchemas.js.map +1 -0
- package/dist/core/llm/openaiSchemas.mjs +107 -0
- package/dist/core/llm/openaiSchemas.mjs.map +1 -0
- package/dist/core/llm/responseFormat.d.ts +25 -0
- package/dist/core/llm/responseFormat.d.ts.map +1 -0
- package/dist/core/llm/responseFormat.js +58 -0
- package/dist/core/llm/responseFormat.js.map +1 -0
- package/dist/core/llm/responseFormat.mjs +32 -0
- package/dist/core/llm/responseFormat.mjs.map +1 -0
- package/dist/core/llm/toOpenAIChatMessage.d.ts +11 -0
- package/dist/core/llm/toOpenAIChatMessage.d.ts.map +1 -0
- package/dist/core/llm/toOpenAIChatMessage.js +95 -0
- package/dist/core/llm/toOpenAIChatMessage.js.map +1 -0
- package/dist/core/llm/toOpenAIChatMessage.mjs +70 -0
- package/dist/core/llm/toOpenAIChatMessage.mjs.map +1 -0
- package/dist/core/llm/usage.d.ts +4 -0
- package/dist/core/llm/usage.d.ts.map +1 -0
- package/dist/core/llm/usage.js +52 -0
- package/dist/core/llm/usage.js.map +1 -0
- package/dist/core/llm/usage.mjs +26 -0
- package/dist/core/llm/usage.mjs.map +1 -0
- package/dist/core/mcp/ClientSideTool.d.ts +10 -0
- package/dist/core/mcp/ClientSideTool.d.ts.map +1 -0
- package/dist/core/mcp/ClientSideTool.js +56 -0
- package/dist/core/mcp/ClientSideTool.js.map +1 -0
- package/dist/core/mcp/ClientSideTool.mjs +31 -0
- package/dist/core/mcp/ClientSideTool.mjs.map +1 -0
- package/dist/core/mcp/IMCPServer.d.ts +78 -0
- package/dist/core/mcp/IMCPServer.d.ts.map +1 -0
- package/dist/core/mcp/IMCPServer.js +63 -0
- package/dist/core/mcp/IMCPServer.js.map +1 -0
- package/dist/core/mcp/IMCPServer.mjs +33 -0
- package/dist/core/mcp/IMCPServer.mjs.map +1 -0
- package/dist/core/mcp/LocalToolMCP.d.ts +39 -0
- package/dist/core/mcp/LocalToolMCP.d.ts.map +1 -0
- package/dist/core/mcp/LocalToolMCP.js +121 -0
- package/dist/core/mcp/LocalToolMCP.js.map +1 -0
- package/dist/core/mcp/LocalToolMCP.mjs +98 -0
- package/dist/core/mcp/LocalToolMCP.mjs.map +1 -0
- package/dist/core/mcp/RemoteMCP.d.ts +67 -0
- package/dist/core/mcp/RemoteMCP.d.ts.map +1 -0
- package/dist/core/mcp/RemoteMCP.js +244 -0
- package/dist/core/mcp/RemoteMCP.js.map +1 -0
- package/dist/core/mcp/RemoteMCP.mjs +222 -0
- package/dist/core/mcp/RemoteMCP.mjs.map +1 -0
- package/dist/core/mcp/ToolSelectorPolicy.d.ts +52 -0
- package/dist/core/mcp/ToolSelectorPolicy.d.ts.map +1 -0
- package/dist/core/mcp/ToolSelectorPolicy.js +108 -0
- package/dist/core/mcp/ToolSelectorPolicy.js.map +1 -0
- package/dist/core/mcp/ToolSelectorPolicy.mjs +90 -0
- package/dist/core/mcp/ToolSelectorPolicy.mjs.map +1 -0
- package/dist/core/mcp/ToolSet.d.ts +31 -0
- package/dist/core/mcp/ToolSet.d.ts.map +1 -0
- package/dist/core/mcp/ToolSet.js +119 -0
- package/dist/core/mcp/ToolSet.js.map +1 -0
- package/dist/core/mcp/ToolSet.mjs +98 -0
- package/dist/core/mcp/ToolSet.mjs.map +1 -0
- package/dist/core/mcp/convertMCPServers.d.ts +22 -0
- package/dist/core/mcp/convertMCPServers.d.ts.map +1 -0
- package/dist/core/mcp/convertMCPServers.js +89 -0
- package/dist/core/mcp/convertMCPServers.js.map +1 -0
- package/dist/core/mcp/convertMCPServers.mjs +64 -0
- package/dist/core/mcp/convertMCPServers.mjs.map +1 -0
- package/dist/core/mcp/executeToolCalls.d.ts +31 -0
- package/dist/core/mcp/executeToolCalls.d.ts.map +1 -0
- package/dist/core/mcp/executeToolCalls.js +168 -0
- package/dist/core/mcp/executeToolCalls.js.map +1 -0
- package/dist/core/mcp/executeToolCalls.mjs +149 -0
- package/dist/core/mcp/executeToolCalls.mjs.map +1 -0
- package/dist/core/mcp/pagination.d.ts +11 -0
- package/dist/core/mcp/pagination.d.ts.map +1 -0
- package/dist/core/mcp/pagination.js +49 -0
- package/dist/core/mcp/pagination.js.map +1 -0
- package/dist/core/mcp/pagination.mjs +24 -0
- package/dist/core/mcp/pagination.mjs.map +1 -0
- package/dist/core/mcp/remoteMcpClient.d.ts +36 -0
- package/dist/core/mcp/remoteMcpClient.d.ts.map +1 -0
- package/dist/core/mcp/remoteMcpClient.js +138 -0
- package/dist/core/mcp/remoteMcpClient.js.map +1 -0
- package/dist/core/mcp/remoteMcpClient.mjs +112 -0
- package/dist/core/mcp/remoteMcpClient.mjs.map +1 -0
- package/dist/core/mcp/toolNames.d.ts +6 -0
- package/dist/core/mcp/toolNames.d.ts.map +1 -0
- package/dist/core/mcp/toolNames.js +59 -0
- package/dist/core/mcp/toolNames.js.map +1 -0
- package/dist/core/mcp/toolNames.mjs +33 -0
- package/dist/core/mcp/toolNames.mjs.map +1 -0
- package/dist/core/mcp/toolSelectors.d.ts +28 -0
- package/dist/core/mcp/toolSelectors.d.ts.map +1 -0
- package/dist/core/mcp/toolSelectors.js +113 -0
- package/dist/core/mcp/toolSelectors.js.map +1 -0
- package/dist/core/mcp/toolSelectors.mjs +78 -0
- package/dist/core/mcp/toolSelectors.mjs.map +1 -0
- package/dist/core/runtime/AgentDefinition.d.ts +23 -0
- package/dist/core/runtime/AgentDefinition.d.ts.map +1 -0
- package/dist/core/runtime/AgentDefinition.js +19 -0
- package/dist/core/runtime/AgentDefinition.js.map +1 -0
- package/dist/core/runtime/AgentDefinition.mjs +1 -0
- package/dist/core/runtime/AgentDefinition.mjs.map +1 -0
- package/dist/core/runtime/AgentThread.d.ts +64 -0
- package/dist/core/runtime/AgentThread.d.ts.map +1 -0
- package/dist/core/runtime/AgentThread.js +1065 -0
- package/dist/core/runtime/AgentThread.js.map +1 -0
- package/dist/core/runtime/AgentThread.mjs +1062 -0
- package/dist/core/runtime/AgentThread.mjs.map +1 -0
- package/dist/core/runtime/AgentThread.types.d.ts +123 -0
- package/dist/core/runtime/AgentThread.types.d.ts.map +1 -0
- package/dist/core/runtime/AgentThread.types.js +46 -0
- package/dist/core/runtime/AgentThread.types.js.map +1 -0
- package/dist/core/runtime/AgentThread.types.mjs +20 -0
- package/dist/core/runtime/AgentThread.types.mjs.map +1 -0
- package/dist/core/runtime/AgentThreadOrchestrator.d.ts +35 -0
- package/dist/core/runtime/AgentThreadOrchestrator.d.ts.map +1 -0
- package/dist/core/runtime/AgentThreadOrchestrator.js +433 -0
- package/dist/core/runtime/AgentThreadOrchestrator.js.map +1 -0
- package/dist/core/runtime/AgentThreadOrchestrator.mjs +418 -0
- package/dist/core/runtime/AgentThreadOrchestrator.mjs.map +1 -0
- package/dist/core/runtime/CreateDynamicSubAgentThread.d.ts +11 -0
- package/dist/core/runtime/CreateDynamicSubAgentThread.d.ts.map +1 -0
- package/dist/core/runtime/CreateDynamicSubAgentThread.js +19 -0
- package/dist/core/runtime/CreateDynamicSubAgentThread.js.map +1 -0
- package/dist/core/runtime/CreateDynamicSubAgentThread.mjs +1 -0
- package/dist/core/runtime/CreateDynamicSubAgentThread.mjs.map +1 -0
- package/dist/core/runtime/DeferredTool.d.ts +34 -0
- package/dist/core/runtime/DeferredTool.d.ts.map +1 -0
- package/dist/core/runtime/DeferredTool.js +321 -0
- package/dist/core/runtime/DeferredTool.js.map +1 -0
- package/dist/core/runtime/DeferredTool.mjs +287 -0
- package/dist/core/runtime/DeferredTool.mjs.map +1 -0
- package/dist/core/runtime/OpenToolCallCloser.d.ts +21 -0
- package/dist/core/runtime/OpenToolCallCloser.d.ts.map +1 -0
- package/dist/core/runtime/OpenToolCallCloser.js +92 -0
- package/dist/core/runtime/OpenToolCallCloser.js.map +1 -0
- package/dist/core/runtime/OpenToolCallCloser.mjs +66 -0
- package/dist/core/runtime/OpenToolCallCloser.mjs.map +1 -0
- package/dist/core/runtime/UserInputMessage.d.ts +16 -0
- package/dist/core/runtime/UserInputMessage.d.ts.map +1 -0
- package/dist/core/runtime/UserInputMessage.js +183 -0
- package/dist/core/runtime/UserInputMessage.js.map +1 -0
- package/dist/core/runtime/UserInputMessage.mjs +157 -0
- package/dist/core/runtime/UserInputMessage.mjs.map +1 -0
- package/dist/core/runtime/contextUsage.d.ts +17 -0
- package/dist/core/runtime/contextUsage.d.ts.map +1 -0
- package/dist/core/runtime/contextUsage.js +56 -0
- package/dist/core/runtime/contextUsage.js.map +1 -0
- package/dist/core/runtime/contextUsage.mjs +28 -0
- package/dist/core/runtime/contextUsage.mjs.map +1 -0
- package/dist/core/runtime/contextUtils.d.ts +30 -0
- package/dist/core/runtime/contextUtils.d.ts.map +1 -0
- package/dist/core/runtime/contextUtils.js +198 -0
- package/dist/core/runtime/contextUtils.js.map +1 -0
- package/dist/core/runtime/contextUtils.mjs +148 -0
- package/dist/core/runtime/contextUtils.mjs.map +1 -0
- package/dist/core/runtime/metrics.d.ts +22 -0
- package/dist/core/runtime/metrics.d.ts.map +1 -0
- package/dist/core/runtime/metrics.js +89 -0
- package/dist/core/runtime/metrics.js.map +1 -0
- package/dist/core/runtime/metrics.mjs +61 -0
- package/dist/core/runtime/metrics.mjs.map +1 -0
- package/dist/core/sandbox/Sandbox.d.ts +121 -0
- package/dist/core/sandbox/Sandbox.d.ts.map +1 -0
- package/dist/core/sandbox/Sandbox.js +572 -0
- package/dist/core/sandbox/Sandbox.js.map +1 -0
- package/dist/core/sandbox/Sandbox.mjs +536 -0
- package/dist/core/sandbox/Sandbox.mjs.map +1 -0
- package/dist/core/sandbox/SandboxErrors.d.ts +30 -0
- package/dist/core/sandbox/SandboxErrors.d.ts.map +1 -0
- package/dist/core/sandbox/SandboxErrors.js +102 -0
- package/dist/core/sandbox/SandboxErrors.js.map +1 -0
- package/dist/core/sandbox/SandboxErrors.mjs +71 -0
- package/dist/core/sandbox/SandboxErrors.mjs.map +1 -0
- package/dist/core/sandbox/SandboxNatsBridge.d.ts +33 -0
- package/dist/core/sandbox/SandboxNatsBridge.d.ts.map +1 -0
- package/dist/core/sandbox/SandboxNatsBridge.js +222 -0
- package/dist/core/sandbox/SandboxNatsBridge.js.map +1 -0
- package/dist/core/sandbox/SandboxNatsBridge.mjs +201 -0
- package/dist/core/sandbox/SandboxNatsBridge.mjs.map +1 -0
- package/dist/core/sandbox/constants.d.ts +10 -0
- package/dist/core/sandbox/constants.d.ts.map +1 -0
- package/dist/core/sandbox/constants.js +37 -0
- package/dist/core/sandbox/constants.js.map +1 -0
- package/dist/core/sandbox/constants.mjs +10 -0
- package/dist/core/sandbox/constants.mjs.map +1 -0
- package/dist/core/sandbox/provider/DaytonaProvider.d.ts +80 -0
- package/dist/core/sandbox/provider/DaytonaProvider.d.ts.map +1 -0
- package/dist/core/sandbox/provider/DaytonaProvider.js +346 -0
- package/dist/core/sandbox/provider/DaytonaProvider.js.map +1 -0
- package/dist/core/sandbox/provider/DaytonaProvider.mjs +326 -0
- package/dist/core/sandbox/provider/DaytonaProvider.mjs.map +1 -0
- package/dist/core/sandbox/provider/Provider.d.ts +83 -0
- package/dist/core/sandbox/provider/Provider.d.ts.map +1 -0
- package/dist/core/sandbox/provider/Provider.js +43 -0
- package/dist/core/sandbox/provider/Provider.js.map +1 -0
- package/dist/core/sandbox/provider/Provider.mjs +17 -0
- package/dist/core/sandbox/provider/Provider.mjs.map +1 -0
- package/dist/core/sandbox/provider/TFYSandboxProvider.d.ts +41 -0
- package/dist/core/sandbox/provider/TFYSandboxProvider.d.ts.map +1 -0
- package/dist/core/sandbox/provider/TFYSandboxProvider.js +180 -0
- package/dist/core/sandbox/provider/TFYSandboxProvider.js.map +1 -0
- package/dist/core/sandbox/provider/TFYSandboxProvider.mjs +147 -0
- package/dist/core/sandbox/provider/TFYSandboxProvider.mjs.map +1 -0
- package/dist/core/sandbox/sandboxImage.d.ts +6 -0
- package/dist/core/sandbox/sandboxImage.d.ts.map +1 -0
- package/dist/core/sandbox/sandboxImage.js +31 -0
- package/dist/core/sandbox/sandboxImage.js.map +1 -0
- package/dist/core/sandbox/sandboxImage.mjs +6 -0
- package/dist/core/sandbox/sandboxImage.mjs.map +1 -0
- package/dist/core/sandbox/sandboxScripts.gen.d.ts +5 -0
- package/dist/core/sandbox/sandboxScripts.gen.d.ts.map +1 -0
- package/dist/core/sandbox/sandboxScripts.gen.js +343 -0
- package/dist/core/sandbox/sandboxScripts.gen.js.map +1 -0
- package/dist/core/sandbox/sandboxScripts.gen.mjs +318 -0
- package/dist/core/sandbox/sandboxScripts.gen.mjs.map +1 -0
- package/dist/core/sandbox/skills/ISkillMounter.d.ts +7 -0
- package/dist/core/sandbox/skills/ISkillMounter.d.ts.map +1 -0
- package/dist/core/sandbox/skills/ISkillMounter.js +19 -0
- package/dist/core/sandbox/skills/ISkillMounter.js.map +1 -0
- package/dist/core/sandbox/skills/ISkillMounter.mjs +1 -0
- package/dist/core/sandbox/skills/ISkillMounter.mjs.map +1 -0
- package/dist/core/sandbox/skills/SkillMounter.d.ts +17 -0
- package/dist/core/sandbox/skills/SkillMounter.d.ts.map +1 -0
- package/dist/core/sandbox/skills/SkillMounter.js +73 -0
- package/dist/core/sandbox/skills/SkillMounter.js.map +1 -0
- package/dist/core/sandbox/skills/SkillMounter.mjs +48 -0
- package/dist/core/sandbox/skills/SkillMounter.mjs.map +1 -0
- package/dist/core/sandbox/skills/constants.d.ts +10 -0
- package/dist/core/sandbox/skills/constants.d.ts.map +1 -0
- package/dist/core/sandbox/skills/constants.js +56 -0
- package/dist/core/sandbox/skills/constants.js.map +1 -0
- package/dist/core/sandbox/skills/constants.mjs +28 -0
- package/dist/core/sandbox/skills/constants.mjs.map +1 -0
- package/dist/core/sandbox/skills/index.d.ts +5 -0
- package/dist/core/sandbox/skills/index.d.ts.map +1 -0
- package/dist/core/sandbox/skills/index.js +40 -0
- package/dist/core/sandbox/skills/index.js.map +1 -0
- package/dist/core/sandbox/skills/index.mjs +11 -0
- package/dist/core/sandbox/skills/index.mjs.map +1 -0
- package/dist/core/tracing/AgentTracing.d.ts +38 -0
- package/dist/core/tracing/AgentTracing.d.ts.map +1 -0
- package/dist/core/tracing/AgentTracing.js +19 -0
- package/dist/core/tracing/AgentTracing.js.map +1 -0
- package/dist/core/tracing/AgentTracing.mjs +1 -0
- package/dist/core/tracing/AgentTracing.mjs.map +1 -0
- package/dist/core/tracing/NoopAgentTracing.d.ts +3 -0
- package/dist/core/tracing/NoopAgentTracing.d.ts.map +1 -0
- package/dist/core/tracing/NoopAgentTracing.js +79 -0
- package/dist/core/tracing/NoopAgentTracing.js.map +1 -0
- package/dist/core/tracing/NoopAgentTracing.mjs +54 -0
- package/dist/core/tracing/NoopAgentTracing.mjs.map +1 -0
- package/dist/core/util/abort.d.ts +2 -0
- package/dist/core/util/abort.d.ts.map +1 -0
- package/dist/core/util/abort.js +38 -0
- package/dist/core/util/abort.js.map +1 -0
- package/dist/core/util/abort.mjs +13 -0
- package/dist/core/util/abort.mjs.map +1 -0
- package/dist/core/util/errorLogFields.d.ts +6 -0
- package/dist/core/util/errorLogFields.d.ts.map +1 -0
- package/dist/core/util/errorLogFields.js +36 -0
- package/dist/core/util/errorLogFields.js.map +1 -0
- package/dist/core/util/errorLogFields.mjs +11 -0
- package/dist/core/util/errorLogFields.mjs.map +1 -0
- package/dist/core/util/promiseUtils.d.ts +7 -0
- package/dist/core/util/promiseUtils.d.ts.map +1 -0
- package/dist/core/util/promiseUtils.js +82 -0
- package/dist/core/util/promiseUtils.js.map +1 -0
- package/dist/core/util/promiseUtils.mjs +55 -0
- package/dist/core/util/promiseUtils.mjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +1 -0
- package/dist/package.json +3 -0
- package/dist/request-reply/client.d.ts +21 -0
- package/dist/request-reply/client.d.ts.map +1 -0
- package/dist/request-reply/client.js +92 -0
- package/dist/request-reply/client.js.map +1 -0
- package/dist/request-reply/client.mjs +67 -0
- package/dist/request-reply/client.mjs.map +1 -0
- package/dist/request-reply/errors.d.ts +23 -0
- package/dist/request-reply/errors.d.ts.map +1 -0
- package/dist/request-reply/errors.js +66 -0
- package/dist/request-reply/errors.js.map +1 -0
- package/dist/request-reply/errors.mjs +39 -0
- package/dist/request-reply/errors.mjs.map +1 -0
- package/dist/request-reply/executor.d.ts +70 -0
- package/dist/request-reply/executor.d.ts.map +1 -0
- package/dist/request-reply/executor.js +267 -0
- package/dist/request-reply/executor.js.map +1 -0
- package/dist/request-reply/executor.mjs +232 -0
- package/dist/request-reply/executor.mjs.map +1 -0
- package/dist/request-reply/index.d.ts +16 -0
- package/dist/request-reply/index.d.ts.map +1 -0
- package/dist/request-reply/index.js +47 -0
- package/dist/request-reply/index.js.map +1 -0
- package/dist/request-reply/index.mjs +16 -0
- package/dist/request-reply/index.mjs.map +1 -0
- package/dist/request-reply/router.d.ts +20 -0
- package/dist/request-reply/router.d.ts.map +1 -0
- package/dist/request-reply/router.js +55 -0
- package/dist/request-reply/router.js.map +1 -0
- package/dist/request-reply/router.mjs +30 -0
- package/dist/request-reply/router.mjs.map +1 -0
- package/dist/request-reply/types.d.ts +25 -0
- package/dist/request-reply/types.d.ts.map +1 -0
- package/dist/request-reply/types.js +54 -0
- package/dist/request-reply/types.js.map +1 -0
- package/dist/request-reply/types.mjs +28 -0
- package/dist/request-reply/types.mjs.map +1 -0
- package/dist/request-reply/utils.d.ts +9 -0
- package/dist/request-reply/utils.d.ts.map +1 -0
- package/dist/request-reply/utils.js +51 -0
- package/dist/request-reply/utils.js.map +1 -0
- package/dist/request-reply/utils.mjs +22 -0
- package/dist/request-reply/utils.mjs.map +1 -0
- package/package.json +127 -6
- package/README.md +0 -4
- package/index.js +0 -1
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// src/core/sandbox/provider/DaytonaProvider.ts
|
|
2
|
+
import { DaytonaError } from "@daytona/sdk";
|
|
3
|
+
import { context } from "@opentelemetry/api";
|
|
4
|
+
import { suppressTracing } from "@opentelemetry/core";
|
|
5
|
+
import { randomUUID } from "crypto";
|
|
6
|
+
import { extractErrorLogFields } from "../../util/errorLogFields.mjs";
|
|
7
|
+
import {
|
|
8
|
+
SandboxFileNotFoundError,
|
|
9
|
+
SandboxFileTooLargeError,
|
|
10
|
+
SandboxNotAvailableError,
|
|
11
|
+
SandboxPathIsDirectoryError
|
|
12
|
+
} from "../SandboxErrors.mjs";
|
|
13
|
+
import { DEFAULT_PREVIEW_URL_EXPIRY_SECONDS, DEFAULT_SANDBOX_NATS_WS_PORT } from "../constants.mjs";
|
|
14
|
+
var SANDBOX_NOT_FOUND_STATUS = 404;
|
|
15
|
+
var SANDBOX_STATE_STARTED = "started";
|
|
16
|
+
var BUILD_STATE_ACTIVE = "active";
|
|
17
|
+
var BUILD_STATE_INACTIVE = "inactive";
|
|
18
|
+
var BUILD_STATE_ERROR = "error";
|
|
19
|
+
var BUILD_STATE_BUILD_FAILED = "build_failed";
|
|
20
|
+
var IMAGE_BUILD_NAME_PREFIX = "trueforge-build-";
|
|
21
|
+
function imageDigest(image) {
|
|
22
|
+
const lastSegment = image.slice(image.lastIndexOf("/") + 1);
|
|
23
|
+
const colon = lastSegment.lastIndexOf(":");
|
|
24
|
+
if (colon === -1) {
|
|
25
|
+
throw new Error(`Sandbox image reference has no tag/digest: ${image}`);
|
|
26
|
+
}
|
|
27
|
+
return lastSegment.slice(colon + 1);
|
|
28
|
+
}
|
|
29
|
+
function deriveImageBuildName(digest) {
|
|
30
|
+
return `${IMAGE_BUILD_NAME_PREFIX}${digest}`;
|
|
31
|
+
}
|
|
32
|
+
function isFailedBuildState(state) {
|
|
33
|
+
return state === BUILD_STATE_ERROR || state === BUILD_STATE_BUILD_FAILED;
|
|
34
|
+
}
|
|
35
|
+
function httpUrlToWsUrl(url) {
|
|
36
|
+
const parsed = new URL(url);
|
|
37
|
+
if (parsed.protocol === "https:") parsed.protocol = "wss:";
|
|
38
|
+
else if (parsed.protocol === "http:") parsed.protocol = "ws:";
|
|
39
|
+
return parsed.toString();
|
|
40
|
+
}
|
|
41
|
+
var DaytonaSandboxProvider = class _DaytonaSandboxProvider {
|
|
42
|
+
tenantName;
|
|
43
|
+
/** Release-owned sandbox image reference; built into a Daytona snapshot and cloned per sandbox. */
|
|
44
|
+
imageUri;
|
|
45
|
+
/** Daytona snapshot name sandboxes are cloned from; the persisted build_ref, or derived from the image digest. */
|
|
46
|
+
buildRef;
|
|
47
|
+
timeoutMs;
|
|
48
|
+
autoStopIntervalInMinutes;
|
|
49
|
+
autoArchiveIntervalInMinutes;
|
|
50
|
+
autoDeleteIntervalInMinutes;
|
|
51
|
+
fileMaxBytesForDownload;
|
|
52
|
+
natsBridgePort;
|
|
53
|
+
previewUrlExpirySeconds;
|
|
54
|
+
logger;
|
|
55
|
+
daytona;
|
|
56
|
+
static cachedSandboxes = /* @__PURE__ */ new Map();
|
|
57
|
+
// De-dupes concurrent recovery attempts on the same sandbox to a single refreshData+start round-trip.
|
|
58
|
+
static inFlightRecoveries = /* @__PURE__ */ new Map();
|
|
59
|
+
constructor(options) {
|
|
60
|
+
this.daytona = options.client;
|
|
61
|
+
this.tenantName = options.tenantName;
|
|
62
|
+
this.imageUri = options.sandboxImage;
|
|
63
|
+
this.buildRef = options.buildRef ?? deriveImageBuildName(imageDigest(options.sandboxImage));
|
|
64
|
+
this.timeoutMs = options.timeoutMs;
|
|
65
|
+
this.autoStopIntervalInMinutes = options.autoStopIntervalInMinutes;
|
|
66
|
+
this.autoArchiveIntervalInMinutes = options.autoArchiveIntervalInMinutes;
|
|
67
|
+
this.autoDeleteIntervalInMinutes = options.autoDeleteIntervalInMinutes;
|
|
68
|
+
this.fileMaxBytesForDownload = options.fileMaxBytesForDownload;
|
|
69
|
+
this.natsBridgePort = options.natsBridgePort ?? DEFAULT_SANDBOX_NATS_WS_PORT;
|
|
70
|
+
this.previewUrlExpirySeconds = options.previewUrlExpirySeconds ?? DEFAULT_PREVIEW_URL_EXPIRY_SECONDS;
|
|
71
|
+
this.logger = options.logger.child({ module: "DaytonaProvider" });
|
|
72
|
+
}
|
|
73
|
+
async getOrCreateSandbox(sandboxId) {
|
|
74
|
+
if (sandboxId) {
|
|
75
|
+
const cached = _DaytonaSandboxProvider.cachedSandboxes.get(sandboxId);
|
|
76
|
+
if (cached) return cached;
|
|
77
|
+
}
|
|
78
|
+
const sandbox = sandboxId ? await this.restoreExistingSandbox(sandboxId) : await this.daytona.create({
|
|
79
|
+
name: `${this.tenantName}.${randomUUID()}`,
|
|
80
|
+
snapshot: this.buildRef,
|
|
81
|
+
autoStopInterval: this.autoStopIntervalInMinutes,
|
|
82
|
+
autoArchiveInterval: this.autoArchiveIntervalInMinutes,
|
|
83
|
+
autoDeleteInterval: this.autoDeleteIntervalInMinutes
|
|
84
|
+
});
|
|
85
|
+
const entry = { sandbox, defaultTimeoutMs: this.timeoutMs };
|
|
86
|
+
_DaytonaSandboxProvider.cachedSandboxes.set(sandbox.name, entry);
|
|
87
|
+
return entry;
|
|
88
|
+
}
|
|
89
|
+
// Returns true iff the caller should retry: either we restarted a stopped sandbox, or the cache entry is missing and the retry will rebuild it via the cold path.
|
|
90
|
+
static recoverSandboxIfStopped(sandboxId) {
|
|
91
|
+
const existing = _DaytonaSandboxProvider.inFlightRecoveries.get(sandboxId);
|
|
92
|
+
if (existing) return existing;
|
|
93
|
+
const cached = _DaytonaSandboxProvider.cachedSandboxes.get(sandboxId);
|
|
94
|
+
if (!cached) return Promise.resolve(true);
|
|
95
|
+
const recovery = (async () => {
|
|
96
|
+
await cached.sandbox.refreshData();
|
|
97
|
+
if (cached.sandbox.state === SANDBOX_STATE_STARTED) return false;
|
|
98
|
+
await cached.sandbox.start();
|
|
99
|
+
return true;
|
|
100
|
+
})().finally(() => {
|
|
101
|
+
_DaytonaSandboxProvider.inFlightRecoveries.delete(sandboxId);
|
|
102
|
+
});
|
|
103
|
+
_DaytonaSandboxProvider.inFlightRecoveries.set(sandboxId, recovery);
|
|
104
|
+
return recovery;
|
|
105
|
+
}
|
|
106
|
+
async executeWithSandboxRecovery(sandboxId, operation) {
|
|
107
|
+
try {
|
|
108
|
+
return await operation();
|
|
109
|
+
} catch (originalError) {
|
|
110
|
+
if (!(originalError instanceof DaytonaError)) throw originalError;
|
|
111
|
+
let recovered;
|
|
112
|
+
try {
|
|
113
|
+
recovered = await _DaytonaSandboxProvider.recoverSandboxIfStopped(sandboxId);
|
|
114
|
+
} catch (recoveryError) {
|
|
115
|
+
this.logger.error("Sandbox recovery failed", {
|
|
116
|
+
...extractErrorLogFields(recoveryError),
|
|
117
|
+
originalError: extractErrorLogFields(originalError)
|
|
118
|
+
});
|
|
119
|
+
throw new Error("Sandbox is unavailable; recovery attempt failed.", { cause: recoveryError });
|
|
120
|
+
}
|
|
121
|
+
if (!recovered) throw originalError;
|
|
122
|
+
try {
|
|
123
|
+
return await operation();
|
|
124
|
+
} catch (retryError) {
|
|
125
|
+
this.logger.error("Sandbox operation failed after successful recovery", {
|
|
126
|
+
...extractErrorLogFields(retryError),
|
|
127
|
+
originalError: extractErrorLogFields(originalError)
|
|
128
|
+
});
|
|
129
|
+
throw retryError;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async restoreExistingSandbox(sandboxId) {
|
|
134
|
+
try {
|
|
135
|
+
const sandbox = await this.daytona.get(sandboxId);
|
|
136
|
+
if (sandbox.state !== SANDBOX_STATE_STARTED) {
|
|
137
|
+
await sandbox.start();
|
|
138
|
+
}
|
|
139
|
+
return sandbox;
|
|
140
|
+
} catch (ex) {
|
|
141
|
+
if (ex instanceof DaytonaError && ex.statusCode === SANDBOX_NOT_FOUND_STATUS) {
|
|
142
|
+
throw new SandboxNotAvailableError(sandboxId);
|
|
143
|
+
}
|
|
144
|
+
throw ex;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async createSandbox() {
|
|
148
|
+
return context.with(suppressTracing(context.active()), async () => {
|
|
149
|
+
const { sandbox } = await this.getOrCreateSandbox();
|
|
150
|
+
this.logger.debug(`Sandbox created: name=${sandbox.name}`);
|
|
151
|
+
return { sandboxId: sandbox.name };
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/** Resolves undefined when no snapshot carries that name; auth/other failures throw. */
|
|
155
|
+
async getSnapshot(name) {
|
|
156
|
+
try {
|
|
157
|
+
return await this.daytona.snapshot.get(name);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (error instanceof DaytonaError && error.statusCode === SANDBOX_NOT_FOUND_STATUS) {
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Drops a build stuck in a terminal-failure state so a fresh create can reuse its
|
|
167
|
+
* deterministic name. A concurrent replica may have deleted it already (404) — that
|
|
168
|
+
* is fine and treated as success.
|
|
169
|
+
*/
|
|
170
|
+
async deleteFailedBuild(snapshot) {
|
|
171
|
+
try {
|
|
172
|
+
await this.daytona.snapshot.delete(snapshot);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (error instanceof DaytonaError && error.statusCode === SANDBOX_NOT_FOUND_STATUS) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
throw error;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
toBuild(state, errorReason) {
|
|
181
|
+
const metadata = { build_ref: this.buildRef, image_uri: this.imageUri };
|
|
182
|
+
switch (state) {
|
|
183
|
+
case BUILD_STATE_ACTIVE:
|
|
184
|
+
return { status: "ready", reason: null, metadata };
|
|
185
|
+
case BUILD_STATE_ERROR:
|
|
186
|
+
case BUILD_STATE_BUILD_FAILED:
|
|
187
|
+
return { status: "failed", reason: errorReason ?? `Sandbox image build failed (${state}).`, metadata };
|
|
188
|
+
default:
|
|
189
|
+
return { status: "pending", reason: `Sandbox image build in progress (${state}).`, metadata };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async buildImage() {
|
|
193
|
+
const existing = await this.getSnapshot(this.buildRef);
|
|
194
|
+
if (existing) {
|
|
195
|
+
if (existing.state === BUILD_STATE_INACTIVE) {
|
|
196
|
+
const activated = await this.daytona.snapshot.activate(existing);
|
|
197
|
+
return this.toBuild(activated.state, activated.errorReason);
|
|
198
|
+
}
|
|
199
|
+
if (!isFailedBuildState(existing.state)) {
|
|
200
|
+
return this.toBuild(existing.state, existing.errorReason);
|
|
201
|
+
}
|
|
202
|
+
await this.deleteFailedBuild(existing);
|
|
203
|
+
}
|
|
204
|
+
void this.daytona.snapshot.create({ name: this.buildRef, image: this.imageUri }).catch((error) => {
|
|
205
|
+
this.logger.error(`Daytona snapshot create failed: name=${this.buildRef}`, extractErrorLogFields(error));
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
status: "pending",
|
|
209
|
+
reason: "Sandbox image build started.",
|
|
210
|
+
metadata: { build_ref: this.buildRef, image_uri: this.imageUri }
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async getImageBuildStatus() {
|
|
214
|
+
const snapshot = await this.getSnapshot(this.buildRef);
|
|
215
|
+
if (!snapshot) {
|
|
216
|
+
return {
|
|
217
|
+
status: "pending",
|
|
218
|
+
reason: "Sandbox image build not started.",
|
|
219
|
+
metadata: { build_ref: this.buildRef, image_uri: this.imageUri }
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return this.toBuild(snapshot.state, snapshot.errorReason);
|
|
223
|
+
}
|
|
224
|
+
async exec(params) {
|
|
225
|
+
return context.with(suppressTracing(context.active()), async () => {
|
|
226
|
+
try {
|
|
227
|
+
return await this.executeWithSandboxRecovery(params.sandboxId, async () => {
|
|
228
|
+
const { sandbox, defaultTimeoutMs } = await this.getOrCreateSandbox(params.sandboxId);
|
|
229
|
+
const response = await sandbox.process.executeCommand(
|
|
230
|
+
params.command,
|
|
231
|
+
params.cwd,
|
|
232
|
+
params.env ?? {},
|
|
233
|
+
params.timeoutSeconds ?? defaultTimeoutMs / 1e3
|
|
234
|
+
);
|
|
235
|
+
return {
|
|
236
|
+
success: true,
|
|
237
|
+
response: { exitCode: response.exitCode, result: response.result }
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
} catch (e) {
|
|
241
|
+
_DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);
|
|
242
|
+
this.logger.error("Sandbox execution error", extractErrorLogFields(e));
|
|
243
|
+
const message = e instanceof Error ? e.message : "Unknown error";
|
|
244
|
+
return { success: false, error: message };
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
async getFileInfo(sandbox, path) {
|
|
249
|
+
const details = await sandbox.fs.getFileDetails(path);
|
|
250
|
+
return { size: details.size, isDir: details.isDir };
|
|
251
|
+
}
|
|
252
|
+
async downloadFile(params) {
|
|
253
|
+
return context.with(suppressTracing(context.active()), async () => {
|
|
254
|
+
try {
|
|
255
|
+
return await this.executeWithSandboxRecovery(params.sandboxId, async () => {
|
|
256
|
+
const { sandbox } = await this.getOrCreateSandbox(params.sandboxId);
|
|
257
|
+
const info = await this.getFileInfo(sandbox, params.path);
|
|
258
|
+
if (info.isDir) {
|
|
259
|
+
throw new SandboxPathIsDirectoryError(params.path);
|
|
260
|
+
}
|
|
261
|
+
if (info.size > this.fileMaxBytesForDownload) {
|
|
262
|
+
throw new SandboxFileTooLargeError(params.path, info.size, this.fileMaxBytesForDownload);
|
|
263
|
+
}
|
|
264
|
+
return await sandbox.fs.downloadFile(params.path);
|
|
265
|
+
});
|
|
266
|
+
} catch (e) {
|
|
267
|
+
if (e instanceof SandboxPathIsDirectoryError || e instanceof SandboxFileTooLargeError) throw e;
|
|
268
|
+
if (e instanceof DaytonaError && e.statusCode === SANDBOX_NOT_FOUND_STATUS) {
|
|
269
|
+
throw new SandboxFileNotFoundError(params.path);
|
|
270
|
+
}
|
|
271
|
+
_DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);
|
|
272
|
+
throw e;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
async uploadFile(params) {
|
|
277
|
+
return context.with(suppressTracing(context.active()), async () => {
|
|
278
|
+
try {
|
|
279
|
+
await this.executeWithSandboxRecovery(params.sandboxId, async () => {
|
|
280
|
+
const { sandbox } = await this.getOrCreateSandbox(params.sandboxId);
|
|
281
|
+
await sandbox.fs.uploadFile(params.content, params.remotePath);
|
|
282
|
+
});
|
|
283
|
+
} catch (e) {
|
|
284
|
+
_DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);
|
|
285
|
+
throw e;
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// Mints a signed, time-limited https preview URL exposing the given sandbox port.
|
|
290
|
+
async getPreviewUrl(params) {
|
|
291
|
+
return context.with(suppressTracing(context.active()), async () => {
|
|
292
|
+
try {
|
|
293
|
+
return await this.executeWithSandboxRecovery(params.sandboxId, async () => {
|
|
294
|
+
const { sandbox } = await this.getOrCreateSandbox(params.sandboxId);
|
|
295
|
+
const signed = await sandbox.getSignedPreviewUrl(params.port, params.expiresInSeconds);
|
|
296
|
+
return signed.url;
|
|
297
|
+
});
|
|
298
|
+
} catch (e) {
|
|
299
|
+
_DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);
|
|
300
|
+
this.logger.error("Failed to create signed preview URL", extractErrorLogFields(e));
|
|
301
|
+
throw e;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
async getNatsBridgeUrl(sandboxId) {
|
|
306
|
+
const previewUrl = await this.getPreviewUrl({
|
|
307
|
+
sandboxId,
|
|
308
|
+
port: this.natsBridgePort,
|
|
309
|
+
expiresInSeconds: this.previewUrlExpirySeconds
|
|
310
|
+
});
|
|
311
|
+
return httpUrlToWsUrl(previewUrl);
|
|
312
|
+
}
|
|
313
|
+
getAdditionalInstructions() {
|
|
314
|
+
return void 0;
|
|
315
|
+
}
|
|
316
|
+
getToolResultDumpDir() {
|
|
317
|
+
return "/tmp/tool-results";
|
|
318
|
+
}
|
|
319
|
+
getGitCredentialsPath() {
|
|
320
|
+
return "/tmp/.git-credentials";
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
export {
|
|
324
|
+
DaytonaSandboxProvider
|
|
325
|
+
};
|
|
326
|
+
//# sourceMappingURL=DaytonaProvider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/sandbox/provider/DaytonaProvider.ts"],"sourcesContent":["import type { Sandbox, Snapshot } from '@daytona/sdk';\nimport { Daytona, DaytonaError } from '@daytona/sdk';\nimport { context } from '@opentelemetry/api';\nimport { suppressTracing } from '@opentelemetry/core';\nimport { randomUUID } from 'crypto';\nimport type { Logger } from 'winston';\nimport { extractErrorLogFields } from '../../util/errorLogFields';\nimport {\n SandboxFileNotFoundError,\n SandboxFileTooLargeError,\n SandboxNotAvailableError,\n SandboxPathIsDirectoryError,\n} from '../SandboxErrors';\nimport { DEFAULT_PREVIEW_URL_EXPIRY_SECONDS, DEFAULT_SANDBOX_NATS_WS_PORT } from '../constants';\nimport type { ExecResult, SandboxBuild, SandboxExecParams, SandboxFileInfo, SandboxProvider } from './Provider';\n\nconst SANDBOX_NOT_FOUND_STATUS = 404;\nconst SANDBOX_STATE_STARTED = 'started';\n\nconst BUILD_STATE_ACTIVE = 'active';\nconst BUILD_STATE_INACTIVE = 'inactive';\nconst BUILD_STATE_ERROR = 'error';\nconst BUILD_STATE_BUILD_FAILED = 'build_failed';\n\nconst IMAGE_BUILD_NAME_PREFIX = 'trueforge-build-';\n\n/**\n * Digest portion of a container image reference (the tag/digest after the final `:`)\n * The release image is always published with an explicit digest tag\n */\nfunction imageDigest(image: string): string {\n const lastSegment = image.slice(image.lastIndexOf('/') + 1);\n const colon = lastSegment.lastIndexOf(':');\n if (colon === -1) {\n throw new Error(`Sandbox image reference has no tag/digest: ${image}`);\n }\n return lastSegment.slice(colon + 1);\n}\n\n/** Deterministic build name per image digest so every server replica converges on one build. */\nfunction deriveImageBuildName(digest: string): string {\n return `${IMAGE_BUILD_NAME_PREFIX}${digest}`;\n}\n\n/** Terminal-failure build states: a build stuck here never becomes ready on its own. */\nfunction isFailedBuildState(state: Snapshot['state']): boolean {\n return state === BUILD_STATE_ERROR || state === BUILD_STATE_BUILD_FAILED;\n}\n\n/** Convert Daytona https preview URLs to wss for the NATS client. */\nfunction httpUrlToWsUrl(url: string): string {\n const parsed = new URL(url);\n if (parsed.protocol === 'https:') parsed.protocol = 'wss:';\n else if (parsed.protocol === 'http:') parsed.protocol = 'ws:';\n return parsed.toString();\n}\n\nexport interface DaytonaSandboxProviderOptions {\n /** Caller-owned Daytona SDK client (credentials / lifetime). */\n client: Daytona;\n tenantName: string;\n /** Release-owned sandbox image reference; built into a Daytona snapshot and cloned per sandbox. */\n sandboxImage: string;\n /**\n * Daytona snapshot name to clone sandboxes from. When omitted it is derived from the image\n * digest. Callers that create sandboxes pass the persisted build_ref so cloning targets the\n * snapshot that was actually built, not a speculative name derived from the current image.\n */\n buildRef?: string | undefined;\n timeoutMs: number;\n autoStopIntervalInMinutes: number;\n autoArchiveIntervalInMinutes: number;\n autoDeleteIntervalInMinutes: number;\n fileMaxBytesForDownload: number;\n /** Defaults to the built-in sandbox NATS WebSocket port (4444). */\n natsBridgePort?: number;\n /** Defaults to 1 hour (same as the gateway's max agent execution time). */\n previewUrlExpirySeconds?: number;\n logger: Logger;\n}\n\nexport class DaytonaSandboxProvider implements SandboxProvider {\n private readonly tenantName: string;\n /** Release-owned sandbox image reference; built into a Daytona snapshot and cloned per sandbox. */\n private readonly imageUri: string;\n /** Daytona snapshot name sandboxes are cloned from; the persisted build_ref, or derived from the image digest. */\n private readonly buildRef: string;\n private readonly timeoutMs: number;\n private readonly autoStopIntervalInMinutes: number;\n private readonly autoArchiveIntervalInMinutes: number;\n private readonly autoDeleteIntervalInMinutes: number;\n private readonly fileMaxBytesForDownload: number;\n private readonly natsBridgePort: number;\n private readonly previewUrlExpirySeconds: number;\n private readonly logger: Logger;\n private readonly daytona: Daytona;\n private static readonly cachedSandboxes = new Map<string, { sandbox: Sandbox; defaultTimeoutMs: number }>();\n // De-dupes concurrent recovery attempts on the same sandbox to a single refreshData+start round-trip.\n private static readonly inFlightRecoveries = new Map<string, Promise<boolean>>();\n\n constructor(options: DaytonaSandboxProviderOptions) {\n this.daytona = options.client;\n this.tenantName = options.tenantName;\n this.imageUri = options.sandboxImage;\n this.buildRef = options.buildRef ?? deriveImageBuildName(imageDigest(options.sandboxImage));\n this.timeoutMs = options.timeoutMs;\n this.autoStopIntervalInMinutes = options.autoStopIntervalInMinutes;\n this.autoArchiveIntervalInMinutes = options.autoArchiveIntervalInMinutes;\n this.autoDeleteIntervalInMinutes = options.autoDeleteIntervalInMinutes;\n this.fileMaxBytesForDownload = options.fileMaxBytesForDownload;\n this.natsBridgePort = options.natsBridgePort ?? DEFAULT_SANDBOX_NATS_WS_PORT;\n this.previewUrlExpirySeconds = options.previewUrlExpirySeconds ?? DEFAULT_PREVIEW_URL_EXPIRY_SECONDS;\n this.logger = options.logger.child({ module: 'DaytonaProvider' });\n }\n\n private async getOrCreateSandbox(sandboxId?: string): Promise<{ sandbox: Sandbox; defaultTimeoutMs: number }> {\n if (sandboxId) {\n const cached = DaytonaSandboxProvider.cachedSandboxes.get(sandboxId);\n if (cached) return cached;\n }\n\n const sandbox = sandboxId\n ? await this.restoreExistingSandbox(sandboxId)\n : await this.daytona.create({\n name: `${this.tenantName}.${randomUUID()}`,\n snapshot: this.buildRef,\n autoStopInterval: this.autoStopIntervalInMinutes,\n autoArchiveInterval: this.autoArchiveIntervalInMinutes,\n autoDeleteInterval: this.autoDeleteIntervalInMinutes,\n });\n\n const entry = { sandbox, defaultTimeoutMs: this.timeoutMs };\n DaytonaSandboxProvider.cachedSandboxes.set(sandbox.name, entry);\n return entry;\n }\n\n // Returns true iff the caller should retry: either we restarted a stopped sandbox, or the cache entry is missing and the retry will rebuild it via the cold path.\n private static recoverSandboxIfStopped(sandboxId: string): Promise<boolean> {\n const existing = DaytonaSandboxProvider.inFlightRecoveries.get(sandboxId);\n if (existing) return existing;\n\n const cached = DaytonaSandboxProvider.cachedSandboxes.get(sandboxId);\n // Cache may have been evicted by a concurrent error path; signal retry so getOrCreateSandbox rebuilds via restoreExistingSandbox.\n if (!cached) return Promise.resolve(true);\n\n const recovery = (async () => {\n await cached.sandbox.refreshData();\n if (cached.sandbox.state === SANDBOX_STATE_STARTED) return false;\n // start() covers both stopped and archived per Daytona; throws on unrecoverable states (error/destroyed).\n await cached.sandbox.start();\n return true;\n })().finally(() => {\n DaytonaSandboxProvider.inFlightRecoveries.delete(sandboxId);\n });\n\n DaytonaSandboxProvider.inFlightRecoveries.set(sandboxId, recovery);\n return recovery;\n }\n\n private async executeWithSandboxRecovery<T>(sandboxId: string, operation: () => Promise<T>): Promise<T> {\n try {\n return await operation();\n } catch (originalError) {\n // TODO: Narrow to a specific Daytona error code once @daytona/sdk exposes one for \"sandbox not running\".\n if (!(originalError instanceof DaytonaError)) throw originalError;\n\n let recovered: boolean;\n try {\n recovered = await DaytonaSandboxProvider.recoverSandboxIfStopped(sandboxId);\n } catch (recoveryError) {\n this.logger.error('Sandbox recovery failed', {\n ...extractErrorLogFields(recoveryError),\n originalError: extractErrorLogFields(originalError),\n });\n throw new Error('Sandbox is unavailable; recovery attempt failed.', { cause: recoveryError });\n }\n\n if (!recovered) throw originalError;\n\n try {\n return await operation();\n } catch (retryError) {\n this.logger.error('Sandbox operation failed after successful recovery', {\n ...extractErrorLogFields(retryError),\n originalError: extractErrorLogFields(originalError),\n });\n // Rethrow as-is so callers can match domain error types (SandboxPathIsDirectoryError, DaytonaError statusCode mappings, etc.).\n throw retryError;\n }\n }\n }\n\n private async restoreExistingSandbox(sandboxId: string): Promise<Sandbox> {\n try {\n const sandbox = await this.daytona.get(sandboxId);\n if (sandbox.state !== SANDBOX_STATE_STARTED) {\n await sandbox.start();\n }\n return sandbox;\n } catch (ex) {\n if (ex instanceof DaytonaError && ex.statusCode === SANDBOX_NOT_FOUND_STATUS) {\n throw new SandboxNotAvailableError(sandboxId);\n }\n throw ex;\n }\n }\n\n async createSandbox(): Promise<{ sandboxId: string }> {\n return context.with(suppressTracing(context.active()), async () => {\n const { sandbox } = await this.getOrCreateSandbox();\n this.logger.debug(`Sandbox created: name=${sandbox.name}`);\n return { sandboxId: sandbox.name };\n });\n }\n\n /** Resolves undefined when no snapshot carries that name; auth/other failures throw. */\n private async getSnapshot(name: string): Promise<Snapshot | undefined> {\n try {\n return await this.daytona.snapshot.get(name);\n } catch (error) {\n if (error instanceof DaytonaError && error.statusCode === SANDBOX_NOT_FOUND_STATUS) {\n return undefined;\n }\n throw error;\n }\n }\n\n /**\n * Drops a build stuck in a terminal-failure state so a fresh create can reuse its\n * deterministic name. A concurrent replica may have deleted it already (404) — that\n * is fine and treated as success.\n */\n private async deleteFailedBuild(snapshot: Snapshot): Promise<void> {\n try {\n await this.daytona.snapshot.delete(snapshot);\n } catch (error) {\n if (error instanceof DaytonaError && error.statusCode === SANDBOX_NOT_FOUND_STATUS) {\n return;\n }\n throw error;\n }\n }\n\n private toBuild(state: Snapshot['state'], errorReason: string | null): SandboxBuild {\n const metadata = { build_ref: this.buildRef, image_uri: this.imageUri };\n switch (state) {\n case BUILD_STATE_ACTIVE:\n return { status: 'ready', reason: null, metadata };\n case BUILD_STATE_ERROR:\n case BUILD_STATE_BUILD_FAILED:\n return { status: 'failed', reason: errorReason ?? `Sandbox image build failed (${state}).`, metadata };\n default:\n // pending / building / pulling / removing / future states: not ready yet.\n return { status: 'pending', reason: `Sandbox image build in progress (${state}).`, metadata };\n }\n }\n\n async buildImage(): Promise<SandboxBuild> {\n const existing = await this.getSnapshot(this.buildRef);\n if (existing) {\n // Daytona parks unused snapshots as 'inactive' after ~2 idle weeks; reactivate rather than rebuild.\n if (existing.state === BUILD_STATE_INACTIVE) {\n const activated = await this.daytona.snapshot.activate(existing);\n return this.toBuild(activated.state, activated.errorReason);\n }\n if (!isFailedBuildState(existing.state)) {\n return this.toBuild(existing.state, existing.errorReason);\n }\n // A failed build keeps the deterministic name occupied and never self-heals, so\n // re-saving settings (which calls buildImage) could never retry. Drop it, then recreate.\n await this.deleteFailedBuild(existing);\n }\n // Fire the create in the background: the SDK's snapshot.create polls until the snapshot is\n // terminal (minutes on a cold image pull), but Daytona registers it on the first request, so\n // progress is observed via getImageBuildStatus. A concurrent-create conflict is harmless.\n void this.daytona.snapshot.create({ name: this.buildRef, image: this.imageUri }).catch((error: unknown) => {\n this.logger.error(`Daytona snapshot create failed: name=${this.buildRef}`, extractErrorLogFields(error));\n });\n return {\n status: 'pending',\n reason: 'Sandbox image build started.',\n metadata: { build_ref: this.buildRef, image_uri: this.imageUri },\n };\n }\n\n async getImageBuildStatus(): Promise<SandboxBuild> {\n const snapshot = await this.getSnapshot(this.buildRef);\n // Read-only: a missing build reports pending; PUT /settings/sandbox-providers starts the build.\n if (!snapshot) {\n return {\n status: 'pending',\n reason: 'Sandbox image build not started.',\n metadata: { build_ref: this.buildRef, image_uri: this.imageUri },\n };\n }\n return this.toBuild(snapshot.state, snapshot.errorReason);\n }\n\n async exec(params: SandboxExecParams): Promise<ExecResult> {\n return context.with(suppressTracing(context.active()), async (): Promise<ExecResult> => {\n try {\n return await this.executeWithSandboxRecovery(params.sandboxId, async () => {\n const { sandbox, defaultTimeoutMs } = await this.getOrCreateSandbox(params.sandboxId);\n const response = await sandbox.process.executeCommand(\n params.command,\n params.cwd,\n params.env ?? {},\n params.timeoutSeconds ?? defaultTimeoutMs / 1000,\n );\n return {\n success: true,\n response: { exitCode: response.exitCode, result: response.result },\n };\n });\n } catch (e: unknown) {\n DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);\n this.logger.error('Sandbox execution error', extractErrorLogFields(e));\n const message = e instanceof Error ? e.message : 'Unknown error';\n return { success: false, error: message };\n }\n });\n }\n\n private async getFileInfo(sandbox: Sandbox, path: string): Promise<SandboxFileInfo> {\n const details = await sandbox.fs.getFileDetails(path);\n return { size: details.size, isDir: details.isDir };\n }\n\n async downloadFile(params: { sandboxId: string; path: string }): Promise<Buffer> {\n return context.with(suppressTracing(context.active()), async () => {\n try {\n return await this.executeWithSandboxRecovery(params.sandboxId, async () => {\n const { sandbox } = await this.getOrCreateSandbox(params.sandboxId);\n\n const info = await this.getFileInfo(sandbox, params.path);\n if (info.isDir) {\n throw new SandboxPathIsDirectoryError(params.path);\n }\n if (info.size > this.fileMaxBytesForDownload) {\n throw new SandboxFileTooLargeError(params.path, info.size, this.fileMaxBytesForDownload);\n }\n\n return await sandbox.fs.downloadFile(params.path);\n });\n } catch (e: unknown) {\n if (e instanceof SandboxPathIsDirectoryError || e instanceof SandboxFileTooLargeError) throw e;\n if (e instanceof DaytonaError && e.statusCode === SANDBOX_NOT_FOUND_STATUS) {\n throw new SandboxFileNotFoundError(params.path);\n }\n DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);\n throw e;\n }\n });\n }\n\n async uploadFile(params: { sandboxId: string; remotePath: string; content: Buffer }): Promise<void> {\n return context.with(suppressTracing(context.active()), async () => {\n try {\n await this.executeWithSandboxRecovery(params.sandboxId, async () => {\n const { sandbox } = await this.getOrCreateSandbox(params.sandboxId);\n await sandbox.fs.uploadFile(params.content, params.remotePath);\n });\n } catch (e: unknown) {\n DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);\n throw e;\n }\n });\n }\n\n // Mints a signed, time-limited https preview URL exposing the given sandbox port.\n private async getPreviewUrl(params: { sandboxId: string; port: number; expiresInSeconds: number }): Promise<string> {\n return context.with(suppressTracing(context.active()), async () => {\n try {\n return await this.executeWithSandboxRecovery(params.sandboxId, async () => {\n const { sandbox } = await this.getOrCreateSandbox(params.sandboxId);\n const signed = await sandbox.getSignedPreviewUrl(params.port, params.expiresInSeconds);\n return signed.url;\n });\n } catch (e: unknown) {\n DaytonaSandboxProvider.cachedSandboxes.delete(params.sandboxId);\n this.logger.error('Failed to create signed preview URL', extractErrorLogFields(e));\n throw e;\n }\n });\n }\n\n async getNatsBridgeUrl(sandboxId: string): Promise<string> {\n // Daytona hands us a signed https preview URL; convert http(s) -> ws(s) for the NATS client.\n const previewUrl = await this.getPreviewUrl({\n sandboxId,\n port: this.natsBridgePort,\n expiresInSeconds: this.previewUrlExpirySeconds,\n });\n return httpUrlToWsUrl(previewUrl);\n }\n\n getAdditionalInstructions(): string | undefined {\n return undefined;\n }\n\n getToolResultDumpDir(): string {\n return '/tmp/tool-results';\n }\n\n getGitCredentialsPath(): string {\n // Isolated container per sandbox; absolute path so GIT_CONFIG_* needs no $HOME expansion.\n return '/tmp/.git-credentials';\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** Command executed in sandbox — exitCode may be non-zero but the infra call succeeded. */
|
|
2
|
+
export interface ExecSuccessResult {
|
|
3
|
+
success: true;
|
|
4
|
+
response: {
|
|
5
|
+
exitCode: number;
|
|
6
|
+
result: string;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
/** Sandbox infrastructure failure — command never ran (e.g. network error, auth failure). */
|
|
10
|
+
export interface ExecErrorResult {
|
|
11
|
+
success: false;
|
|
12
|
+
error: string;
|
|
13
|
+
}
|
|
14
|
+
export type ExecResult = ExecSuccessResult | ExecErrorResult;
|
|
15
|
+
/**
|
|
16
|
+
* Wraps a value in single quotes for safe use in a shell command. Inner single quotes are
|
|
17
|
+
* escaped via the standard shell idiom: ' -> '\''. Use for any user-controlled value that is
|
|
18
|
+
* interpolated into an exec command string.
|
|
19
|
+
*/
|
|
20
|
+
export declare function shellEscape(value: string): string;
|
|
21
|
+
/** Throws if the exec result indicates failure (infra error or non-zero exit code). */
|
|
22
|
+
export declare function ensureExecSuccess(result: ExecResult): void;
|
|
23
|
+
export interface SandboxFileInfo {
|
|
24
|
+
size: number;
|
|
25
|
+
isDir: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** Parameters for a single sandbox command. */
|
|
28
|
+
export interface SandboxExecParams {
|
|
29
|
+
sandboxId: string;
|
|
30
|
+
command: string;
|
|
31
|
+
cwd?: string | undefined;
|
|
32
|
+
env?: Record<string, string> | undefined;
|
|
33
|
+
/** Overrides the provider's default exec timeout (e.g. for long skill downloads). */
|
|
34
|
+
timeoutSeconds?: number | undefined;
|
|
35
|
+
}
|
|
36
|
+
export type SandboxInit = Omit<SandboxExecParams, 'sandboxId'>;
|
|
37
|
+
export type SandboxBuildStatus = 'pending' | 'ready' | 'failed';
|
|
38
|
+
/** Provider-specific opaque build metadata (string map). */
|
|
39
|
+
export type SandboxBuildMetadata = Record<string, string>;
|
|
40
|
+
export interface SandboxBuild {
|
|
41
|
+
status: SandboxBuildStatus;
|
|
42
|
+
/** Human-readable detail for the current status (shown to the user); null when ready. */
|
|
43
|
+
reason: string | null;
|
|
44
|
+
/** Provider-specific build details; null when the provider has none. */
|
|
45
|
+
metadata: SandboxBuildMetadata | null;
|
|
46
|
+
}
|
|
47
|
+
export interface SandboxProvider {
|
|
48
|
+
/**
|
|
49
|
+
* Ensures the release image is being built into the provider's backing store and
|
|
50
|
+
* returns its current status. Idempotent: an already-built image reports `ready`;
|
|
51
|
+
* a fresh build starts in the background and reports `pending`.
|
|
52
|
+
*/
|
|
53
|
+
buildImage(): Promise<SandboxBuild>;
|
|
54
|
+
/** Current build status of the release image. Read-only: never kicks off a build. */
|
|
55
|
+
getImageBuildStatus(): Promise<SandboxBuild>;
|
|
56
|
+
createSandbox(): Promise<{
|
|
57
|
+
sandboxId: string;
|
|
58
|
+
}>;
|
|
59
|
+
exec(params: SandboxExecParams): Promise<ExecResult>;
|
|
60
|
+
/** Provider-specific instructions appended to the agent system prompt. */
|
|
61
|
+
getAdditionalInstructions(): string | undefined;
|
|
62
|
+
/** Directory inside the sandbox where large tool responses are dumped. */
|
|
63
|
+
getToolResultDumpDir(sandboxId: string): string;
|
|
64
|
+
/** Absolute path for the git credential-store file (per logical sandbox when sharing a pod). */
|
|
65
|
+
getGitCredentialsPath(sandboxId: string): string;
|
|
66
|
+
/** Downloads a file from the sandbox as a Buffer. Throws SandboxFileNotFoundError / SandboxNotAvailableError / SandboxPathIsDirectoryError / SandboxFileTooLargeError. */
|
|
67
|
+
downloadFile(params: {
|
|
68
|
+
sandboxId: string;
|
|
69
|
+
path: string;
|
|
70
|
+
}): Promise<Buffer>;
|
|
71
|
+
/** Uploads a file to the sandbox. */
|
|
72
|
+
uploadFile(params: {
|
|
73
|
+
sandboxId: string;
|
|
74
|
+
remotePath: string;
|
|
75
|
+
content: Buffer;
|
|
76
|
+
}): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Returns a ready-to-use `ws(s)://` URL for this sandbox's pod-local NATS broker, which the
|
|
79
|
+
* gateway connects to as the MCP responder. Throws on failure (caller retries on a later exec).
|
|
80
|
+
*/
|
|
81
|
+
getNatsBridgeUrl(sandboxId: string): Promise<string>;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=Provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Provider.d.ts","sourceRoot":"","sources":["../../../../src/core/sandbox/provider/Provider.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,IAAI,CAAC;IACd,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,6FAA6F;AAC7F,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAO1D;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,+CAA+C;AAC/C,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACzC,qFAAqF;IACrF,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAGD,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;AAE/D,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhE,4DAA4D;AAC5D,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,yFAAyF;IACzF,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wEAAwE;IACxE,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IACpC,qFAAqF;IACrF,mBAAmB,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,aAAa,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD,0EAA0E;IAC1E,yBAAyB,IAAI,MAAM,GAAG,SAAS,CAAC;IAChD,0EAA0E;IAC1E,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAChD,gGAAgG;IAChG,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACjD,0KAA0K;IAC1K,YAAY,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,qCAAqC;IACrC,UAAU,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9F;;;OAGG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/core/sandbox/provider/Provider.ts
|
|
21
|
+
var Provider_exports = {};
|
|
22
|
+
__export(Provider_exports, {
|
|
23
|
+
ensureExecSuccess: () => ensureExecSuccess,
|
|
24
|
+
shellEscape: () => shellEscape
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(Provider_exports);
|
|
27
|
+
function shellEscape(value) {
|
|
28
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
29
|
+
}
|
|
30
|
+
function ensureExecSuccess(result) {
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
throw new Error(result.error);
|
|
33
|
+
}
|
|
34
|
+
if (result.response.exitCode !== 0) {
|
|
35
|
+
throw new Error(`(exit code ${String(result.response.exitCode)}): ${result.response.result}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
39
|
+
0 && (module.exports = {
|
|
40
|
+
ensureExecSuccess,
|
|
41
|
+
shellEscape
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=Provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/sandbox/provider/Provider.ts"],"sourcesContent":["/** Command executed in sandbox — exitCode may be non-zero but the infra call succeeded. */\nexport interface ExecSuccessResult {\n success: true;\n response: { exitCode: number; result: string };\n}\n\n/** Sandbox infrastructure failure — command never ran (e.g. network error, auth failure). */\nexport interface ExecErrorResult {\n success: false;\n error: string;\n}\n\nexport type ExecResult = ExecSuccessResult | ExecErrorResult;\n\n/**\n * Wraps a value in single quotes for safe use in a shell command. Inner single quotes are\n * escaped via the standard shell idiom: ' -> '\\''. Use for any user-controlled value that is\n * interpolated into an exec command string.\n */\nexport function shellEscape(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/** Throws if the exec result indicates failure (infra error or non-zero exit code). */\nexport function ensureExecSuccess(result: ExecResult): void {\n if (!result.success) {\n throw new Error(result.error);\n }\n if (result.response.exitCode !== 0) {\n throw new Error(`(exit code ${String(result.response.exitCode)}): ${result.response.result}`);\n }\n}\n\nexport interface SandboxFileInfo {\n size: number;\n isDir: boolean;\n}\n\n/** Parameters for a single sandbox command. */\nexport interface SandboxExecParams {\n sandboxId: string;\n command: string;\n cwd?: string | undefined;\n env?: Record<string, string> | undefined;\n /** Overrides the provider's default exec timeout (e.g. for long skill downloads). */\n timeoutSeconds?: number | undefined;\n}\n\n// An init command a producer (e.g. a skill mounter) hands to the Sandbox, which supplies `sandboxId`.\nexport type SandboxInit = Omit<SandboxExecParams, 'sandboxId'>;\n\nexport type SandboxBuildStatus = 'pending' | 'ready' | 'failed';\n\n/** Provider-specific opaque build metadata (string map). */\nexport type SandboxBuildMetadata = Record<string, string>;\n\nexport interface SandboxBuild {\n status: SandboxBuildStatus;\n /** Human-readable detail for the current status (shown to the user); null when ready. */\n reason: string | null;\n /** Provider-specific build details; null when the provider has none. */\n metadata: SandboxBuildMetadata | null;\n}\n\nexport interface SandboxProvider {\n /**\n * Ensures the release image is being built into the provider's backing store and\n * returns its current status. Idempotent: an already-built image reports `ready`;\n * a fresh build starts in the background and reports `pending`.\n */\n buildImage(): Promise<SandboxBuild>;\n /** Current build status of the release image. Read-only: never kicks off a build. */\n getImageBuildStatus(): Promise<SandboxBuild>;\n createSandbox(): Promise<{ sandboxId: string }>;\n exec(params: SandboxExecParams): Promise<ExecResult>;\n /** Provider-specific instructions appended to the agent system prompt. */\n getAdditionalInstructions(): string | undefined;\n /** Directory inside the sandbox where large tool responses are dumped. */\n getToolResultDumpDir(sandboxId: string): string;\n /** Absolute path for the git credential-store file (per logical sandbox when sharing a pod). */\n getGitCredentialsPath(sandboxId: string): string;\n /** Downloads a file from the sandbox as a Buffer. Throws SandboxFileNotFoundError / SandboxNotAvailableError / SandboxPathIsDirectoryError / SandboxFileTooLargeError. */\n downloadFile(params: { sandboxId: string; path: string }): Promise<Buffer>;\n /** Uploads a file to the sandbox. */\n uploadFile(params: { sandboxId: string; remotePath: string; content: Buffer }): Promise<void>;\n\n /**\n * Returns a ready-to-use `ws(s)://` URL for this sandbox's pod-local NATS broker, which the\n * gateway connects to as the MCP responder. Throws on failure (caller retries on a later exec).\n */\n getNatsBridgeUrl(sandboxId: string): Promise<string>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBO,SAAS,YAAY,OAAuB;AACjD,SAAO,IAAI,MAAM,QAAQ,MAAM,OAAO,CAAC;AACzC;AAGO,SAAS,kBAAkB,QAA0B;AAC1D,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI,MAAM,OAAO,KAAK;AAAA,EAC9B;AACA,MAAI,OAAO,SAAS,aAAa,GAAG;AAClC,UAAM,IAAI,MAAM,cAAc,OAAO,OAAO,SAAS,QAAQ,CAAC,MAAM,OAAO,SAAS,MAAM,EAAE;AAAA,EAC9F;AACF;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/core/sandbox/provider/Provider.ts
|
|
2
|
+
function shellEscape(value) {
|
|
3
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
4
|
+
}
|
|
5
|
+
function ensureExecSuccess(result) {
|
|
6
|
+
if (!result.success) {
|
|
7
|
+
throw new Error(result.error);
|
|
8
|
+
}
|
|
9
|
+
if (result.response.exitCode !== 0) {
|
|
10
|
+
throw new Error(`(exit code ${String(result.response.exitCode)}): ${result.response.result}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
ensureExecSuccess,
|
|
15
|
+
shellEscape
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=Provider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/sandbox/provider/Provider.ts"],"sourcesContent":["/** Command executed in sandbox — exitCode may be non-zero but the infra call succeeded. */\nexport interface ExecSuccessResult {\n success: true;\n response: { exitCode: number; result: string };\n}\n\n/** Sandbox infrastructure failure — command never ran (e.g. network error, auth failure). */\nexport interface ExecErrorResult {\n success: false;\n error: string;\n}\n\nexport type ExecResult = ExecSuccessResult | ExecErrorResult;\n\n/**\n * Wraps a value in single quotes for safe use in a shell command. Inner single quotes are\n * escaped via the standard shell idiom: ' -> '\\''. Use for any user-controlled value that is\n * interpolated into an exec command string.\n */\nexport function shellEscape(value: string): string {\n return `'${value.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/** Throws if the exec result indicates failure (infra error or non-zero exit code). */\nexport function ensureExecSuccess(result: ExecResult): void {\n if (!result.success) {\n throw new Error(result.error);\n }\n if (result.response.exitCode !== 0) {\n throw new Error(`(exit code ${String(result.response.exitCode)}): ${result.response.result}`);\n }\n}\n\nexport interface SandboxFileInfo {\n size: number;\n isDir: boolean;\n}\n\n/** Parameters for a single sandbox command. */\nexport interface SandboxExecParams {\n sandboxId: string;\n command: string;\n cwd?: string | undefined;\n env?: Record<string, string> | undefined;\n /** Overrides the provider's default exec timeout (e.g. for long skill downloads). */\n timeoutSeconds?: number | undefined;\n}\n\n// An init command a producer (e.g. a skill mounter) hands to the Sandbox, which supplies `sandboxId`.\nexport type SandboxInit = Omit<SandboxExecParams, 'sandboxId'>;\n\nexport type SandboxBuildStatus = 'pending' | 'ready' | 'failed';\n\n/** Provider-specific opaque build metadata (string map). */\nexport type SandboxBuildMetadata = Record<string, string>;\n\nexport interface SandboxBuild {\n status: SandboxBuildStatus;\n /** Human-readable detail for the current status (shown to the user); null when ready. */\n reason: string | null;\n /** Provider-specific build details; null when the provider has none. */\n metadata: SandboxBuildMetadata | null;\n}\n\nexport interface SandboxProvider {\n /**\n * Ensures the release image is being built into the provider's backing store and\n * returns its current status. Idempotent: an already-built image reports `ready`;\n * a fresh build starts in the background and reports `pending`.\n */\n buildImage(): Promise<SandboxBuild>;\n /** Current build status of the release image. Read-only: never kicks off a build. */\n getImageBuildStatus(): Promise<SandboxBuild>;\n createSandbox(): Promise<{ sandboxId: string }>;\n exec(params: SandboxExecParams): Promise<ExecResult>;\n /** Provider-specific instructions appended to the agent system prompt. */\n getAdditionalInstructions(): string | undefined;\n /** Directory inside the sandbox where large tool responses are dumped. */\n getToolResultDumpDir(sandboxId: string): string;\n /** Absolute path for the git credential-store file (per logical sandbox when sharing a pod). */\n getGitCredentialsPath(sandboxId: string): string;\n /** Downloads a file from the sandbox as a Buffer. Throws SandboxFileNotFoundError / SandboxNotAvailableError / SandboxPathIsDirectoryError / SandboxFileTooLargeError. */\n downloadFile(params: { sandboxId: string; path: string }): Promise<Buffer>;\n /** Uploads a file to the sandbox. */\n uploadFile(params: { sandboxId: string; remotePath: string; content: Buffer }): Promise<void>;\n\n /**\n * Returns a ready-to-use `ws(s)://` URL for this sandbox's pod-local NATS broker, which the\n * gateway connects to as the MCP responder. Throws on failure (caller retries on a later exec).\n */\n getNatsBridgeUrl(sandboxId: string): Promise<string>;\n}\n"],"mappings":";AAmBO,SAAS,YAAY,OAAuB;AACjD,SAAO,IAAI,MAAM,QAAQ,MAAM,OAAO,CAAC;AACzC;AAGO,SAAS,kBAAkB,QAA0B;AAC1D,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI,MAAM,OAAO,KAAK;AAAA,EAC9B;AACA,MAAI,OAAO,SAAS,aAAa,GAAG;AAClC,UAAM,IAAI,MAAM,cAAc,OAAO,OAAO,SAAS,QAAQ,CAAC,MAAM,OAAO,SAAS,MAAM,EAAE;AAAA,EAC9F;AACF;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Logger } from 'winston';
|
|
2
|
+
import { type ExecResult, type SandboxBuild, type SandboxExecParams, type SandboxProvider } from './Provider';
|
|
3
|
+
export interface TFYSandboxProviderOptions {
|
|
4
|
+
serverUrl: string;
|
|
5
|
+
natsBridgeUrl: string;
|
|
6
|
+
tenantName: string;
|
|
7
|
+
fileMaxBytesForDownload: number;
|
|
8
|
+
defaultExecTimeoutMs?: number | undefined;
|
|
9
|
+
logger: Logger;
|
|
10
|
+
}
|
|
11
|
+
export declare class TFYSandboxProvider implements SandboxProvider {
|
|
12
|
+
private readonly serverUrl;
|
|
13
|
+
private readonly natsBridgeUrl;
|
|
14
|
+
private readonly tenantName;
|
|
15
|
+
private readonly fileMaxBytesForDownload;
|
|
16
|
+
private readonly defaultExecTimeoutSeconds;
|
|
17
|
+
private readonly logger;
|
|
18
|
+
constructor(options: TFYSandboxProviderOptions);
|
|
19
|
+
private static readonly readyBuild;
|
|
20
|
+
buildImage(): Promise<SandboxBuild>;
|
|
21
|
+
getImageBuildStatus(): Promise<SandboxBuild>;
|
|
22
|
+
createSandbox(): Promise<{
|
|
23
|
+
sandboxId: string;
|
|
24
|
+
}>;
|
|
25
|
+
exec(params: SandboxExecParams): Promise<ExecResult>;
|
|
26
|
+
private getFileInfo;
|
|
27
|
+
downloadFile(params: {
|
|
28
|
+
sandboxId: string;
|
|
29
|
+
path: string;
|
|
30
|
+
}): Promise<Buffer>;
|
|
31
|
+
uploadFile(params: {
|
|
32
|
+
sandboxId: string;
|
|
33
|
+
remotePath: string;
|
|
34
|
+
content: Buffer;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
getNatsBridgeUrl(): Promise<string>;
|
|
37
|
+
getAdditionalInstructions(): string;
|
|
38
|
+
getToolResultDumpDir(sandboxId: string): string;
|
|
39
|
+
getGitCredentialsPath(sandboxId: string): string;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=TFYSandboxProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TFYSandboxProvider.d.ts","sourceRoot":"","sources":["../../../../src/core/sandbox/provider/TFYSandboxProvider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGtC,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,iBAAiB,EAEtB,KAAK,eAAe,EACrB,MAAM,YAAY,CAAC;AAYpB,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,MAAM,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;CAChB;AAOD,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAS;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAEhC,YAAY,OAAO,EAAE,yBAAyB,EAO7C;IAGD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAIhC;IAEF,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC,CAElC;IAED,mBAAmB,IAAI,OAAO,CAAC,YAAY,CAAC,CAE3C;IAED,aAAa,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAI9C;IAEK,IAAI,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CA+CzD;YAEa,WAAW;IAanB,YAAY,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB/E;IAEK,UAAU,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CASlG;IAGD,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAElC;IAED,yBAAyB,IAAI,MAAM,CAOlC;IAED,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE9C;IAED,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/C;CACF"}
|