Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions src/spark_character/codex_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,31 @@ def call_codex(
"--output-last-message", str(out_path),
"-",
]
result = subprocess.run(
cmd,
input=combined.encode("utf-8"),
capture_output=True,
timeout=spec.timeout_seconds,
)
try:
result = subprocess.run(
cmd,
input=combined.encode("utf-8"),
capture_output=True,
timeout=spec.timeout_seconds,
)
except FileNotFoundError as exc:
# Guards the eval/judge driver against a raw stack trace when the
# codex CLI is not installed or CODEX_PATH points at a removed
# binary. Preserves the operator's next move (install codex or
# set CODEX_PATH) instead of leaking the OSError text.
raise RuntimeError(
f"codex binary not found at {spec.binary!r}. Install the codex CLI "
f"or set CODEX_PATH / SPARK_CODEX_PATH to its absolute path."
) from exc
except subprocess.TimeoutExpired as exc:
# Closes the silent-hang window when codex exec exceeds the
# configured timeout; surfaces the actual budget so the operator
# can raise CodexSpec.timeout_seconds rather than guess.
raise RuntimeError(
f"codex exec timed out after {spec.timeout_seconds:.0f}s. "
f"Increase CodexSpec.timeout_seconds or check that the codex "
f"CLI is responsive."
) from exc
if result.returncode != 0:
stderr = result.stderr.decode("utf-8", errors="replace") if result.stderr else ""
raise RuntimeError(f"codex exec failed (rc={result.returncode}): {stderr.strip()[:300]}")
Expand Down