| """Detached worker for one durable terminal task.""" |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| import hashlib |
| import subprocess |
| import time |
| from pathlib import Path |
|
|
| from .artifacts import ArtifactStore |
| from .events import EventLog |
| from .sandbox import sandbox_argv, sandbox_environment |
| from .security import SecretRedactor |
| from .tasks import TaskStore |
|
|
|
|
| def run_terminal_task( |
| *, |
| task_root: str, |
| task_id: str, |
| workspace: str, |
| command: str, |
| ) -> int: |
| store = TaskStore(workspace) |
| expected_root = Path(task_root).expanduser().resolve() |
| if store.root != expected_root: |
| raise ValueError("task root does not match the selected workspace") |
| started = time.monotonic() |
| completed = subprocess.run( |
| sandbox_argv(workspace, command), |
| cwd=Path(workspace).expanduser().resolve(), |
| env=sandbox_environment(), |
| stdin=subprocess.DEVNULL, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE, |
| text=True, |
| check=False, |
| ) |
| current = store.get(task_id) |
| if current.status == "cancelled": |
| return 0 |
| redactor = SecretRedactor() |
| stdout = redactor.redact(completed.stdout) |
| stderr = redactor.redact(completed.stderr) |
| combined = stdout + (("\n" + stderr) if stderr else "") |
| artifact = ArtifactStore(workspace).put_text( |
| combined, |
| source=f"task:{task_id}", |
| session_id_sha256=current.session_id_sha256, |
| ) |
| result = { |
| "ok": completed.returncode == 0, |
| "exit_code": completed.returncode, |
| "stdout": stdout, |
| "stderr": stderr, |
| "elapsed_s": time.monotonic() - started, |
| "output_sha256": hashlib.sha256(combined.encode("utf-8")).hexdigest(), |
| "artifact_id": artifact.artifact_id, |
| } |
| updated = store.update( |
| task_id, |
| status="completed" if completed.returncode == 0 else "failed", |
| status_message="completed" if completed.returncode == 0 else "command failed", |
| progress={"finished": True}, |
| result=result, |
| error="" if completed.returncode == 0 else stderr, |
| process_id=0, |
| ) |
| EventLog(workspace).append( |
| "task_finished", |
| session_id_sha256=updated.session_id_sha256, |
| task_id=updated.task_id, |
| status=updated.status, |
| detail={ |
| "exit_code": completed.returncode, |
| "artifact_id": artifact.artifact_id, |
| "output_sha256": result["output_sha256"], |
| }, |
| ) |
| return completed.returncode |
|
|
|
|
| def main() -> int: |
| parser = argparse.ArgumentParser(description="Run one Nexum durable task") |
| parser.add_argument("--task-root", required=True) |
| parser.add_argument("--task-id", required=True) |
| parser.add_argument("--workspace", required=True) |
| parser.add_argument("--command", required=True) |
| args = parser.parse_args() |
| return run_terminal_task( |
| task_root=args.task_root, |
| task_id=args.task_id, |
| workspace=args.workspace, |
| command=args.command, |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|