Skip to content

Commit 9e1e11d

Browse files
Merge branch 'main' into 285-external-mode-github-action-inputs-mode-plumbing-and-compatibility
2 parents 0e42a9e + 157d763 commit 9e1e11d

2 files changed

Lines changed: 19 additions & 22 deletions

File tree

web/schemas/execution.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from pydantic import BaseModel, Field, field_validator
1212
from typing import List, Optional
1313

14+
from autograder.models.config.setup import AssetConfig
1415
from sandbox_manager.models.sandbox_models import ResponseCategory, Language
1516
from web.schemas.submission import SubmissionFileData
1617

@@ -23,6 +24,7 @@ class DeliberateCodeExecutionRequest(BaseModel):
2324
submission_files: List[SubmissionFileData] = Field(..., description="List of files to be executed, including their content.")
2425
program_command: str = Field(..., description="The command to execute the program (e.g., 'python main.py', 'java Main', 'node app.js', './a.out').")
2526
test_cases: Optional[List[List[str]]] = Field(None, description="Optional list of test cases to be evaluated. Each test case is a list of inputs/arguments.")
27+
assets: Optional[List[AssetConfig]] = Field(default_factory=list, description="Optional list of assets to be injected into the sandbox before execution.")
2628

2729
@field_validator('language')
2830
@classmethod

web/service/deliberate_execution_service.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import asyncio
99

1010
from autograder.models.dataclass.submission import SubmissionFile
11+
from autograder.services.assets.resolver import AssetSourceResolver
1112
from sandbox_manager.manager import get_sandbox_manager
1213
from sandbox_manager.models.sandbox_models import Language, ResponseCategory, CommandResponse
1314
from web.config.logging import get_logger
@@ -158,6 +159,20 @@ async def execute_code(request: DeliberateCodeExecutionRequest) -> DeliberateCod
158159
sandbox.prepare_workdir(files_dict)
159160
logger.info("Prepared workdir with %d file(s)", len(files_dict))
160161

162+
# Resolve and inject assets if provided
163+
if request.assets:
164+
logger.info("Resolving and injecting %d assets for deliberate execution", len(request.assets))
165+
asset_resolver = AssetSourceResolver()
166+
resolved_assets = await asyncio.to_thread(
167+
asset_resolver.resolve_assets,
168+
request.assets
169+
)
170+
await asyncio.to_thread(
171+
sandbox.inject_assets,
172+
resolved_assets
173+
)
174+
logger.info("Successfully injected %d assets", len(resolved_assets))
175+
161176
# Determine test cases to run (at least 1 empty run if none provided)
162177
test_cases = request.test_cases if request.test_cases else [[]]
163178

@@ -170,28 +185,8 @@ async def execute_code(request: DeliberateCodeExecutionRequest) -> DeliberateCod
170185

171186
return DeliberateCodeExecutionResponse(results=execution_results)
172187

173-
except Exception as e: # pylint: disable=broad-exception-caught
174-
logger.error("Execution failed: %s", e, exc_info=True)
175-
# Return error response instead of raising
176-
return DeliberateCodeExecutionResponse(
177-
results=[
178-
DeliberateCodeExecutionResult(
179-
output="",
180-
category=ResponseCategory.SYSTEM_ERROR,
181-
error_message=f"Execution failed: {str(e)}",
182-
execution_time=0.0
183-
)
184-
]
185-
)
186-
187188
finally:
188-
# Release sandbox back to pool
189-
if sandbox:
189+
# Always release sandbox back to pool
190+
if sandbox and sandbox_manager:
190191
sandbox_manager.release_sandbox(language, sandbox)
191192
logger.info("Released sandbox for %s", language.value)
192-
193-
194-
195-
196-
197-

0 commit comments

Comments
 (0)