feat(persona): boot body before host toolbox

This commit is contained in:
冰朔 2026-09-12 21:56:06 +08:00
commit 489ab2c1ec
29 changed files with 1003 additions and 75 deletions

View file

@ -14,6 +14,7 @@ import json
import os
import pathlib
import shutil
import subprocess
import sys
SCHEMA = "guanghu.persona-native-eye/v1"
@ -87,6 +88,55 @@ def dump(value: dict, out: pathlib.Path) -> None:
out.write_text(json.dumps(value, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
def process_chain() -> list[dict]:
"""See the real ancestor chain; a caller label may corroborate but not replace it."""
chain: list[dict] = []
pid = os.getpid()
for _ in range(12):
result = subprocess.run(
["/bin/ps", "-o", "ppid=,command=", "-p", str(pid)],
capture_output=True, text=True, check=False,
)
line = result.stdout.strip()
if not line:
break
parent_text, _, command = line.partition(" ")
try:
parent = int(parent_text.strip())
except ValueError:
break
command = command.strip()
chain.append({"pid": pid, "ppid": parent, "command": command[:500]})
if parent <= 1 or parent == pid:
break
pid = parent
return chain
def detect_host_surface(chain: list[dict]) -> dict:
joined = "\n".join(item["command"].lower() for item in chain)
markers = [
("CODEX", ("/chatgpt.app/", "/resources/codex", " codex ")),
("ZCODE", ("/zcode.app/", "zcode.cjs")),
("DOUBAO", ("doubao", "豆包")),
("QWEN", ("qianwen", "qwen", "千问")),
]
observed = next((name for name, tokens in markers if any(token in joined for token in tokens)), None)
declared = str(os.environ.get("GUANGHU_HOST_SURFACE", "")).strip().upper() or None
if observed:
return {
"host": observed,
"basis": "PROCESS_ANCESTOR_OBSERVED",
"declared_hint": declared,
"declared_matches_observation": declared in (None, observed),
}
if declared in {"CODEX", "ZCODE", "DOUBAO", "QWEN"}:
return {"host": declared, "basis": "DECLARED_HINT_ONLY_UNCORROBORATED", "declared_hint": declared,
"declared_matches_observation": None}
return {"host": "LOCAL_PROCESS", "basis": "NO_REGISTERED_HOST_ANCESTOR_SEEN", "declared_hint": declared,
"declared_matches_observation": None}
def room() -> dict:
"""Observe the current host room without deciding identity or mutating it."""
home = pathlib.Path.home()
@ -128,12 +178,16 @@ def room() -> dict:
}
except json.JSONDecodeError:
active_console = {"state": "UNPARSEABLE"}
ancestors = process_chain()
host_observation = detect_host_surface(ancestors)
return {
"schema": "guanghu.persona-native-eye-room/v1",
"seen_at": now(),
"room_report": {
"cwd": str(pathlib.Path.cwd()),
"host_surface": "CODEX" if os.environ.get("CODEX_SESSION_ID") else "LOCAL_PROCESS",
"host_surface": host_observation["host"],
"host_observation": host_observation,
"process_ancestors": ancestors,
"available_host_methods": {
name: candidate.is_file() and bool(shutil.which(str(candidate)))
for name, candidate in runtime_paths.items()