agent-exec transport b11015860dac4bb8a1943889211374b7/0dd2eb729ad2

This commit is contained in:
agent-exec-transport
2026-10-15 20:02:36 +00:00
parent 93aba6ba95
commit 6b00f4f8b0
8 changed files with 832 additions and 353 deletions
+195
View File
@@ -5,11 +5,14 @@ does not contact providers or launch real agent runs.
"""
from __future__ import annotations
import json
import re
import shutil
import subprocess
from collections.abc import Sequence
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from scripts.agent_exec_config import (
ALLOWED_PLACEHOLDERS,
@@ -23,6 +26,34 @@ _PROBE_TIMEOUT_SECONDS = 5
MAX_UNIT_PACKET_BYTES = 262_144
UNIT_PACKET_DISPLAY_MARKER = "<unit-packet>"
TERMINAL_STATUSES = (
"completed",
"failed",
"blocked",
"cancelled",
"failed-unknown",
"scope-expansion",
)
TERMINAL_RECORD_SCHEMA: dict[str, Any] = {
"type": "object",
"required": [
"terminal_status",
"summary",
"changed_files",
"evidence",
"scope_expansion",
],
"properties": {
"terminal_status": {"enum": list(TERMINAL_STATUSES)},
"summary": {"type": "string"},
"changed_files": {"type": "array", "items": {"type": "string"}},
"evidence": {"type": "array", "items": {"type": "string"}},
"scope_expansion": {"type": ["string", "null"]},
},
}
# Bounds the backwards brace scan over one final message.
_MAX_TERMINAL_TEXT_CHARS = 262_144
_PLACEHOLDER_MAP = {
"${workspace}": "workspace",
"${unit_packet}": "unit_packet",
@@ -378,17 +409,177 @@ def _read_unit_packet_text(path: Path) -> str:
def _build_bounded_unit_prompt(packet_text: str) -> str:
schema = json.dumps(TERMINAL_RECORD_SCHEMA, separators=(",", ":"))
return (
"Implement exactly the supplied bounded implementation unit. "
"Work only inside the current workspace. "
"Leave all changes uncommitted. "
"Do not expand scope beyond the unit packet. "
"Return a structured final result matching the unit's required schema.\n\n"
"--- TERMINAL RECORD ---\n\n"
"End your final message with exactly one terminal record: a single-line "
"JSON object that validates against this JSON Schema:\n"
f"{schema}\n"
"Use terminal_status completed only when the unit is fully implemented. "
"Use blocked, cancelled, failed-unknown, failed, or scope-expansion "
"otherwise. A missing or invalid terminal record fails the attempt.\n\n"
"--- BOUNDED IMPLEMENTATION UNIT PACKET ---\n\n"
f"{packet_text}"
)
def extract_terminal_record(text: str | None) -> dict[str, Any] | None:
"""Return the last valid terminal record embedded in one final message."""
if not isinstance(text, str) or not text:
return None
text = text[-_MAX_TERMINAL_TEXT_CHARS:]
decoder = json.JSONDecoder()
pos = text.rfind("{")
while pos != -1:
try:
candidate, _ = decoder.raw_decode(text, pos)
except json.JSONDecodeError:
candidate = None
record = _valid_terminal_record(candidate)
if record is not None:
return record
pos = text.rfind("{", 0, pos)
return None
def _valid_terminal_record(obj: object) -> dict[str, Any] | None:
if not isinstance(obj, dict):
return None
status = obj.get("terminal_status")
if not isinstance(status, str):
return None
status = status.strip().replace("_", "-")
if status not in TERMINAL_STATUSES:
return None
if not isinstance(obj.get("summary"), str):
return None
for key in ("changed_files", "evidence"):
items = obj.get(key)
if not isinstance(items, list) or any(not isinstance(i, str) for i in items):
return None
if "scope_expansion" not in obj or not (
obj["scope_expansion"] is None or isinstance(obj["scope_expansion"], str)
):
return None
record = dict(obj)
record["terminal_status"] = status
return record
def decode_terminal_record(
adapter: str,
*,
event_lines: Sequence[str | None],
stdout_tail: str,
result_text: str | None,
) -> dict[str, Any] | None:
"""Decode the worker terminal record from the adapter's real output.
``event_lines`` are recent complete stdout lines that may carry a terminal
envelope, oldest first; ``None`` marks an envelope line too large to keep.
Event-stream adapters are read only from their final assistant/result
envelope, so prompt echoes and tool output never count as a record.
"""
if adapter in ("cursor", "claude"):
return extract_terminal_record(_cursor_final_text(event_lines))
if adapter == "antigravity":
return extract_terminal_record(_agy_final_text(event_lines, stdout_tail))
if adapter == "pi":
return extract_terminal_record(_pi_final_text(event_lines))
record = extract_terminal_record(result_text)
if record is None:
record = extract_terminal_record(stdout_tail)
return record
def _event_objects(event_lines: Sequence[str | None]) -> list[dict[str, Any] | None]:
"""Newest-first parsed events; ``None`` keeps the oversized-envelope marker."""
out: list[dict[str, Any] | None] = []
for line in reversed(event_lines):
if line is None:
out.append(None)
continue
try:
obj = json.loads(line)
except json.JSONDecodeError:
continue
if isinstance(obj, dict):
out.append(obj)
return out
def _cursor_final_text(event_lines: Sequence[str | None]) -> str | None:
for obj in _event_objects(event_lines):
if obj is None:
return None
if obj.get("type") != "result":
continue
if obj.get("is_error") is not False or obj.get("subtype") != "success":
return None
text = obj.get("result")
return text if isinstance(text, str) else None
return None
def _agy_final_text(
event_lines: Sequence[str | None], stdout_tail: str
) -> str | None:
candidates = _event_objects(event_lines)
try:
whole = json.loads(stdout_tail.strip())
except json.JSONDecodeError:
whole = None
if isinstance(whole, dict):
candidates.append(whole)
for obj in candidates:
if obj is None:
return None
if obj.get("event") == "result":
payload = obj.get("result")
elif "event" not in obj and "response" in obj:
payload = obj
else:
continue
if not isinstance(payload, dict):
return None
if payload.get("is_error") or payload.get("error"):
return None
text = payload.get("response")
return text if isinstance(text, str) else None
return None
def _pi_final_text(event_lines: Sequence[str | None]) -> str | None:
for obj in _event_objects(event_lines):
if obj is None:
return None
if obj.get("type") != "message_end":
continue
message = obj.get("message")
if not isinstance(message, dict) or message.get("role") != "assistant":
continue
if message.get("stopReason") in ("error", "aborted"):
return None
content = message.get("content")
if isinstance(content, str):
return content
if not isinstance(content, list):
return None
return "".join(
block["text"]
for block in content
if isinstance(block, dict)
and block.get("type") == "text"
and isinstance(block.get("text"), str)
)
return None
def _expand_argv(
items: tuple[str, ...],
values: dict[str, str],
@@ -480,11 +671,15 @@ def _sanitize_display(
__all__ = [
"MAX_UNIT_PACKET_BYTES",
"TERMINAL_RECORD_SCHEMA",
"TERMINAL_STATUSES",
"UNIT_PACKET_DISPLAY_MARKER",
"AdapterProbe",
"AdapterSpec",
"BUILTIN_SPECS",
"Invocation",
"build_invocation",
"decode_terminal_record",
"extract_terminal_record",
"probe_adapter",
]