fix: make Codex hooks transactional

This commit is contained in:
ZacharyZhang-NY committed 2026-07-20 02:41:42 -04:00
1 parent c3602da5f3
commit cb6173e6ee
17 files changed
+2308 -870

No files matched your search

+19 -37
View File
@@ -9,13 +9,14 @@ import re
import sys
from typing import Any, Dict, List, Optional, Tuple
from ._strict_json import JsonObject, parse_json_object
AGENT_KEY = "cursor"
GUARD_SCRIPT = "guard.py"
AUDIT_SCRIPT = "hook.py"
HOOK_TIMEOUT_SECONDS = 10
JsonObject = Dict[str, Any]
CursorHooks = Dict[str, List[JsonObject]]
@@ -48,10 +49,6 @@ class _ParsedArgument:
next_index: int
class _DuplicateKey(ValueError):
pass
def runtime_root() -> str:
return os.path.join(os.path.expanduser("~"), ".elydora")
@@ -109,7 +106,10 @@ def _read_posix_argument(command: str, start: int) -> Optional[_ParsedArgument]:
def _parse_posix_command(command: str) -> Optional[Tuple[str, str]]:
executable = _read_posix_argument(command, 0)
if executable is None or command[executable.next_index:executable.next_index + 1] != " ":
if (
executable is None
or command[executable.next_index : executable.next_index + 1] != " "
):
return None
script = _read_posix_argument(command, executable.next_index + 1)
if script is None or script.next_index != len(command):
@@ -142,10 +142,13 @@ def _parse_powershell_command(command: str) -> Optional[Tuple[str, str]]:
if not command.startswith("& "):
return None
executable = _read_powershell_argument(command, 2)
if executable is None or command[executable.next_index:executable.next_index + 1] != " ":
if (
executable is None
or command[executable.next_index : executable.next_index + 1] != " "
):
return None
script = _read_powershell_argument(command, executable.next_index + 1)
if script is None or command[script.next_index:] != "; exit $LASTEXITCODE":
if script is None or command[script.next_index :] != "; exit $LASTEXITCODE":
return None
return executable.value, script.value
@@ -196,27 +199,6 @@ def _managed_agent_id(
return agent_id if agent_id not in {"", ".", ".."} else None
def _unique_object(pairs: List[Tuple[str, Any]]) -> JsonObject:
result: JsonObject = {}
for key, value in pairs:
if key in result:
raise _DuplicateKey(f'duplicate field "{key}"')
result[key] = value
return result
def parse_json_object(raw: str, label: str) -> JsonObject:
try:
value = json.loads(raw, object_pairs_hook=_unique_object)
except _DuplicateKey as error:
raise ValueError(f"Failed to parse {label}: {error}") from error
except json.JSONDecodeError as error:
raise ValueError(f"Failed to parse {label}: {error}") from error
if not isinstance(value, dict):
raise ValueError(f"{label} must contain a JSON object")
return value
def _read_hooks(value: Any, label: str) -> CursorHooks:
if value is None:
raise ValueError(f'{label} field "hooks" must be an object')
@@ -227,9 +209,7 @@ def _read_hooks(value: Any, label: str) -> CursorHooks:
if not isinstance(handlers, list):
raise ValueError(f'{label} field "hooks.{event}" must be an array')
if not all(isinstance(handler, dict) for handler in handlers):
raise ValueError(
f'{label} field "hooks.{event}" must contain objects'
)
raise ValueError(f'{label} field "hooks.{event}" must contain objects')
hooks[event] = list(handlers)
return hooks
@@ -344,9 +324,11 @@ def runtime_contracts(hooks: CursorHooks) -> List[RuntimeContract]:
if key not in audits or key not in failures:
continue
agent_directory = os.path.join(runtime_root(), agent_id)
contracts.append(RuntimeContract(
agent_id,
os.path.join(agent_directory, GUARD_SCRIPT),
os.path.join(agent_directory, AUDIT_SCRIPT),
))
contracts.append(
RuntimeContract(
agent_id,
os.path.join(agent_directory, GUARD_SCRIPT),
os.path.join(agent_directory, AUDIT_SCRIPT),
)
)
return contracts