Codex application override added.

This commit is contained in:
Storm Dragon committed 2026-10-28 20:46:12 -04:00
1 parent b887f6ea95
commit 7c53cb39d4
23 files changed
+1771 -155

No files matched your search

+159
View File
@@ -0,0 +1,159 @@
#!/usr/bin/env python3
# Copyright (c) 2026 Storm Dragon
# SPDX-License-Identifier: GPL-3.0-or-later
"""Private X11 bridge/PTY test, with fake speech and no live Codex requests."""
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import time
import tty
def fixture_shell():
tty.setraw(0)
os.write(1, "\x1b[2J\x1b[HOpenAI Codex\x1b[22;1H› ".encode())
while True:
data = os.read(0, 4096)
if not data:
return
os.write(1, data)
def main():
from native_terminal import KeyboardFixture, SpeechServer, wait_for
if os.environ.get("FENRIR_PRIVATE_X11") != "1" or not os.environ.get("DISPLAY"):
raise SystemExit("Use xvfb-run -a env FENRIR_PRIVATE_X11=1")
repo = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location("bridge", repo / "tools/codex_bridge.py")
bridge = importlib.util.module_from_spec(spec)
spec.loader.exec_module(bridge)
with tempfile.TemporaryDirectory(prefix="fenrir-codex-native-") as directory:
root = Path(directory)
(root / "keyboard").mkdir()
(root / "keyboard/custom.toml").write_bytes((repo / "config/keyboard/desktop.toml").read_bytes())
(root / "home").mkdir()
(root / "settings.toml").write_text('version=3\n[presentation.sound]\nenabled=false\n'
f'[remote]\nsocket_file="{root / "remote.sock"}"\n')
shell = root / "shell"
shell.write_text(f'#!{sys.executable}\nimport runpy, sys\nsys.argv=[{str(Path(__file__).resolve())!r}, "--shell"]\nrunpy.run_path(sys.argv[0], run_name="__main__")\n')
shell.chmod(0o700)
server = SpeechServer(root / "speech.sock")
keyboard = KeyboardFixture()
env = dict(os.environ, HOME=str(root / "home"), TMPDIR=str(root),
FENRIR_TEST_BINARY=os.environ.get("FENRIR_TEST_BINARY", str(repo / "fenrir")),
SPEECHD_ADDRESS="unix_socket:" + str(root / "speech.sock"),
LOGNAME="Username", USER="Username", LC_ALL="C", LANGUAGE="C")
process = subprocess.Popen(["xterm", "-geometry", "100x24", "-e", sys.executable,
str(repo / "tests/native_terminal.py"), "--outer", str(root)], env=env)
watcher = None
try:
wait_for(lambda: (root / "started").exists(), "reader startup")
state = json.loads((root / "started").read_text())
subprocess.run(["xdotool", "windowfocus", "--sync", str(state["window"])], check=True)
wait_for(lambda: any("OpenAI Codex" in item for item in server.events), "fixture screen ready")
def spoken(text, start):
wait_for(lambda: any(text in item for item in server.events[start:]), f"speech {text!r}")
def action(chord, expected):
start = len(server.events)
keyboard.key(chord)
spoken(expected, start)
action("Insert+a", "Application Default")
action("c", "Codex")
action("Return", "Codex application override selected")
action("Insert+0", "Waiting for Codex bridge")
session = "fixture-session"
transcript = root / "session.jsonl"
def append_record(kind, payload):
with transcript.open("ab") as stream:
stream.write((json.dumps({"type": kind, "payload": payload}) + "\n").encode())
append_record("session_meta", {"id": session})
append_record("event_msg", {"type": "agent_message", "message": "Existing reply"})
statusPath = root / "status.json"
bridge.write_status(statusPath, "working")
activePath = root / "active.json"
bridge.write_json(activePath, {"key":"fixture", "epoch":1})
config = {"pid": os.getpid(), "started": bridge.process_info(os.getpid())[2],
"window": str(state["window"]), "terminal": 1, "session": session,
"transcript": str(transcript), "status_path": str(statusPath), "lock_path": str(root / "watch.lock"),
"active_path": str(activePath), "key":"fixture"}
watcher = subprocess.Popen([sys.executable, str(repo / "tools/codex_bridge.py"), "--watch", json.dumps(config)], env=env)
wait_for(lambda: (root / "watch.lock").exists(), "bridge startup")
# Wait for baseline delivery by polling the manual history command.
start = len(server.events)
for _ in range(20):
keyboard.key("Insert+1")
time.sleep(0.2)
if "Existing reply" in server.events[start:]:
break
else:
raise AssertionError("baseline history unavailable")
action("Insert+0", "Codex working")
# The raw fixture echoes terminal cursor escapes just like a TUI.
# Actual XTest arrows must speak the unchanged composer character.
keyboard.key("h", "e", "l", "l", "o")
action("Left", "o")
action("Left", "l")
action("Right", "o")
start = len(server.events)
append_record("event_msg", {"type": "item_completed", "item": {"type": "CommandExecution", "aggregated_output": "Private tool result"}})
message = json.dumps({"type": "event_msg", "payload": {"type": "item_completed", "item": {"type": "AgentMessage", "content": [{"type": "Text", "text": "A completed progress update."}]}}}) + "\n"
with transcript.open("ab") as stream:
stream.write(message[:-3].encode())
time.sleep(0.5)
assert not any("completed progress" in item or "Private tool result" in item for item in server.events[start:])
with transcript.open("ab") as stream:
stream.write(message[-3:].encode())
spoken("A completed progress update.", start)
time.sleep(2.3) # Include a complete heartbeat/retry interval.
assert server.events[start:].count("A completed progress update.") == 1, server.events[start:]
action("Insert+1", "A completed progress update.")
action("Insert+2", "Existing reply")
start = len(server.events)
longReply = "Long reply " + "word " * 2000
append_record("event_msg", {"type": "agent_message", "message": longReply})
spoken("Long reply", start)
assert any(item.strip() == longReply.strip() for item in server.events[start:]), "long reply truncated"
watcher.terminate()
watcher.wait(timeout=3)
bridge.write_status(statusPath, "working")
start = len(server.events)
watcher = subprocess.Popen([sys.executable, str(repo / "tools/codex_bridge.py"), "--watch", json.dumps(config)], env=env)
time.sleep(0.6)
assert not any("Long reply" in item for item in server.events[start:]), "replay spoke old history"
bridge.write_status(statusPath, "done")
time.sleep(0.4)
action("Insert+0", "Codex finished")
action("Insert+a", "Application Codex")
action("d", "Default")
action("Return", "Default settings restored")
keyboard.key("Insert+q")
wait_for(lambda: (root / "finished").exists(), "reader exit")
assert not server.errors, server.errors
print("PASS: real private PTY/override/socket bridge, composer Left/Right feedback, baseline history, completed messages only, one announcement, long replies, replay and status")
except BaseException:
print("Recent private speech:", server.events[-15:], file=sys.stderr)
if (root / "status.json").exists():
print("Bridge status:", (root / "status.json").read_text(), file=sys.stderr)
if (root / "reader-errors").exists():
print("Reader errors:", (root / "reader-errors").read_text()[-2500:], file=sys.stderr)
raise
finally:
if watcher is not None and watcher.poll() is None:
watcher.terminate()
watcher.wait(timeout=3)
process.terminate()
try:
process.wait(timeout=3)
except subprocess.TimeoutExpired:
process.kill()
keyboard.close()
server.close()
if __name__ == "__main__":
fixture_shell() if "--shell" in sys.argv else main()