Execute a task with OpenSpace. Args: task: Task instruction context: Additional context. Communication callers may pass: - conversation_history: prior user/assistant turns - channel_context: platform/chat metadata and
(
self,
task: str,
context: Optional[Dict[str, Any]] = None,
workspace_dir: Optional[str] = None,
max_iterations: Optional[int] = None,
task_id: Optional[str] = None,
capture_skill_dir: Optional[str] = None,
)
| 301 | raise |
| 302 | |
| 303 | async def execute( |
| 304 | self, |
| 305 | task: str, |
| 306 | context: Optional[Dict[str, Any]] = None, |
| 307 | workspace_dir: Optional[str] = None, |
| 308 | max_iterations: Optional[int] = None, |
| 309 | task_id: Optional[str] = None, |
| 310 | capture_skill_dir: Optional[str] = None, |
| 311 | ) -> Dict[str, Any]: |
| 312 | """ |
| 313 | Execute a task with OpenSpace. |
| 314 | |
| 315 | Args: |
| 316 | task: Task instruction |
| 317 | context: Additional context. Communication callers may pass: |
| 318 | - conversation_history: prior user/assistant turns |
| 319 | - channel_context: platform/chat metadata and attachments |
| 320 | - session_key: stable external session identifier |
| 321 | workspace_dir: Working directory |
| 322 | max_iterations: Max iterations override |
| 323 | task_id: External task ID for recording/logging. If None, generates a random one. |
| 324 | This allows external callers (e.g., OSWorld) to specify their own task ID |
| 325 | so recordings can be easily matched with benchmark results. |
| 326 | capture_skill_dir: Preferred directory for CAPTURED skills. In multi-host-agent |
| 327 | scenarios, this should be the calling host agent's skill directory so |
| 328 | newly captured skills are written to the correct location. |
| 329 | """ |
| 330 | if not self._initialized: |
| 331 | raise RuntimeError( |
| 332 | "OpenSpace not initialized. " |
| 333 | "Call await tool_layer.initialize() first or use async with." |
| 334 | ) |
| 335 | |
| 336 | _TASK_WAIT_TIMEOUT = 660 # slightly longer than MCP tool timeout (600s) |
| 337 | if self._running: |
| 338 | logger.info( |
| 339 | "OpenSpace is busy — waiting up to %ds for the current task to finish...", |
| 340 | _TASK_WAIT_TIMEOUT, |
| 341 | ) |
| 342 | try: |
| 343 | await asyncio.wait_for( |
| 344 | self._task_done.wait(), timeout=_TASK_WAIT_TIMEOUT |
| 345 | ) |
| 346 | except asyncio.TimeoutError: |
| 347 | raise RuntimeError( |
| 348 | f"OpenSpace is still running after waiting {_TASK_WAIT_TIMEOUT}s. " |
| 349 | "Please try again later." |
| 350 | ) |
| 351 | |
| 352 | logger.info("="*60) |
| 353 | logger.info(f"Task: {task[:100]}...") |
| 354 | logger.info("="*60) |
| 355 | |
| 356 | self._running = True |
| 357 | self._task_done.clear() |
| 358 | self._last_evolved_skills = [] # Reset per-execution tracking |
| 359 | self._capture_skill_dir = capture_skill_dir |
| 360 | start_time = asyncio.get_event_loop().time() |
no test coverage detected