feat(runtime): consume governed Activity Core closes
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a06ba0-10aa-7ea0-b20a-4f3fac39efe9
This commit is contained in:
parent
0e6d795aa4
commit
d00ffcb402
22 changed files with 1218 additions and 148 deletions
|
|
@ -25,6 +25,7 @@ from typing import Any
|
|||
import httpx
|
||||
|
||||
from rein_aharness.intake import resolve_target_repo
|
||||
from rein_aharness.repository_grant import RepositoryGrant, RepositoryGrantError
|
||||
from rein_aharness.taskspec import TaskSpec, TaskSpecError
|
||||
|
||||
DEFAULT_ACTIVITY_CORE_URL = "http://127.0.0.1:8010"
|
||||
|
|
@ -41,10 +42,12 @@ class OpsRunError(RuntimeError):
|
|||
*,
|
||||
action: str | None = None,
|
||||
status_code: int | None = None,
|
||||
code: str | None = None,
|
||||
) -> None:
|
||||
super().__init__(message)
|
||||
self.action = action
|
||||
self.status_code = status_code
|
||||
self.code = code
|
||||
|
||||
@property
|
||||
def lease_rejected(self) -> bool:
|
||||
|
|
@ -73,11 +76,25 @@ class OpsRun:
|
|||
approach_hint: str | None = None
|
||||
harness_profile_ref: str | None = None
|
||||
execution_refs: dict[str, Any] = field(default_factory=dict)
|
||||
repository_grant: RepositoryGrant | None = None
|
||||
result: dict[str, Any] = field(default_factory=dict)
|
||||
close_disposition: str | None = None
|
||||
close_intent_digest: str | None = None
|
||||
raw: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
@classmethod
|
||||
def from_api(cls, data: dict[str, Any]) -> "OpsRun":
|
||||
grant = None
|
||||
if data.get("repository_grant") is not None:
|
||||
try:
|
||||
grant = RepositoryGrant.from_mapping(data["repository_grant"])
|
||||
except RepositoryGrantError as exc:
|
||||
run_id = str(data.get("id") or "unknown")[:200]
|
||||
raise OpsRunError(
|
||||
f"ops_run {run_id} has an invalid repository_grant",
|
||||
action="decode",
|
||||
code="invalid_repository_grant",
|
||||
) from exc
|
||||
return cls(
|
||||
id=str(data.get("id") or ""),
|
||||
activity_definition_id=str(data.get("activity_definition_id") or ""),
|
||||
|
|
@ -97,7 +114,14 @@ class OpsRun:
|
|||
approach_hint=data.get("approach_hint"),
|
||||
harness_profile_ref=data.get("harness_profile_ref"),
|
||||
execution_refs=dict(data.get("execution_refs") or {}),
|
||||
repository_grant=grant,
|
||||
result=dict(data.get("result") or {}),
|
||||
close_disposition=_bounded_optional_string(
|
||||
data.get("close_disposition"), 80
|
||||
),
|
||||
close_intent_digest=_bounded_optional_string(
|
||||
data.get("close_intent_digest"), 128
|
||||
),
|
||||
raw=data,
|
||||
)
|
||||
|
||||
|
|
@ -279,6 +303,7 @@ class ActivityCoreOpsClient:
|
|||
f"{action} ops_run {run_id} failed: HTTP {exc.response.status_code}",
|
||||
action=action,
|
||||
status_code=exc.response.status_code,
|
||||
code=_response_error_code(exc.response),
|
||||
) from exc
|
||||
except httpx.HTTPError as exc:
|
||||
raise OpsRunError(
|
||||
|
|
@ -313,6 +338,7 @@ def ops_run_to_taskspec(
|
|||
hub_task_id=run.id,
|
||||
completion_event_type=completion_event_type,
|
||||
timeout_seconds=timeout_seconds,
|
||||
repository_grant=run.repository_grant,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -325,3 +351,19 @@ def resolve_ops_target(run: OpsRun, config: OpsRunConfig | None = None) -> Path:
|
|||
repo_map=cfg.repo_map,
|
||||
repo_roots=cfg.repo_roots,
|
||||
)
|
||||
|
||||
|
||||
def _response_error_code(response: httpx.Response) -> str | None:
|
||||
try:
|
||||
payload = response.json()
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
detail = payload.get("detail") if isinstance(payload, dict) else None
|
||||
code = detail.get("code") if isinstance(detail, dict) else None
|
||||
return _bounded_optional_string(code, 80)
|
||||
|
||||
|
||||
def _bounded_optional_string(value: Any, limit: int) -> str | None:
|
||||
if not isinstance(value, str) or not value:
|
||||
return None
|
||||
return value[:limit]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue