Explorer
/proc/118/root/tmp/hermes_kernel_lb6lj5v8/hermes_kernel_runner.py
← Zurück ↓ Download
"""Auto-generated Hermes session-kernel runner. One exec cell per request."""
import contextlib
import io
import json
import os
import sys
import traceback

_SENTINEL = os.environ["HERMES_KERNEL_SENTINEL"]
_CAPTURE_LIMIT = 1000000
_SPILL_DIR = os.environ.get("HERMES_KERNEL_SPILL_DIR", "")
_SPILL_CAP = 5000000

# The persistent cell namespace. `__name__` is `__main__` so scripts behave
# like the per-call path; builtins resolve normally through exec.
GLOBALS = {"__name__": "__main__", "__builtins__": __builtins__}

_real_stdout = sys.stdout


def _bounded(text, spill_name=None):
    """Clip to the inline cap; spill the FULL text to disk when clipping.

    Returns (clipped_text, clipped?, spill_path_or_empty). Spill is
    best-effort — a failed write degrades to plain clipping.
    """
    if len(text) <= _CAPTURE_LIMIT:
        return text, False, ""
    spill_path = ""
    if _SPILL_DIR and spill_name:
        try:
            spill_path = os.path.join(_SPILL_DIR, spill_name)
            with open(spill_path, "w", encoding="utf-8", errors="replace") as f:
                f.write(text[:_SPILL_CAP])
                if len(text) > _SPILL_CAP:
                    f.write("\n\n[... spill capped ...]")
        except Exception:
            spill_path = ""
    return text[: _CAPTURE_LIMIT], True, spill_path


def _reply(payload):
    body = json.dumps(payload, ensure_ascii=False).encode("utf-8")
    _real_stdout.buffer.write(
        ("\n" + _SENTINEL + " " + str(len(body)) + "\n").encode("utf-8")
    )
    _real_stdout.buffer.write(body)
    _real_stdout.buffer.flush()


def main():
    execution_count = 0
    for line in sys.stdin:
        line = line.strip()
        if not line:
            continue
        try:
            request = json.loads(line)
        except ValueError:
            continue
        execution_count += 1
        out, err = io.StringIO(), io.StringIO()
        status = "ok"
        trace = ""
        try:
            with contextlib.redirect_stdout(out), contextlib.redirect_stderr(err):
                exec(compile(request["code"], "<cell>", "exec"), GLOBALS)
        except SystemExit as exc:
            status = "exit"
            trace = "SystemExit: " + repr(exc.code)
        except BaseException:
            status = "error"
            trace = traceback.format_exc()
        stdout_text, stdout_clipped, stdout_spill = _bounded(
            out.getvalue(), "cell_%06d_stdout.txt" % execution_count
        )
        stderr_text, stderr_clipped, _ = _bounded(err.getvalue())
        _reply(
            {
                "id": request.get("id", ""),
                "status": status,
                "stdout": stdout_text,
                "stderr": stderr_text,
                "stdout_clipped": stdout_clipped,
                "stderr_clipped": stderr_clipped,
                "stdout_spill_path": stdout_spill,
                "traceback": trace,
                "execution_count": execution_count,
            }
        )
        if status == "exit":
            break


if __name__ == "__main__":
    main()