1427 lines
55 KiB
Python
Executable File
1427 lines
55 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Deterministic Codex CLI stand-in used by the offline integration suite."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
import datetime as dt
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import re
|
|
import signal
|
|
import socket
|
|
import struct
|
|
import sys
|
|
import termios
|
|
import threading
|
|
import time
|
|
import uuid
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
MODELS = [
|
|
"codex-auto-review",
|
|
"gpt-5.2",
|
|
"gpt-5.3-codex-spark",
|
|
"gpt-5.4",
|
|
"gpt-5.4-mini",
|
|
"gpt-5.5",
|
|
"gpt-5.6-luna",
|
|
"gpt-5.6-sol",
|
|
"gpt-5.6-terra",
|
|
]
|
|
|
|
MODEL_METADATA = {
|
|
"gpt-5.6-sol": (272000, ["low", "medium", "high", "xhigh", "max", "ultra"]),
|
|
"gpt-5.6-terra": (272000, ["low", "medium", "high", "xhigh", "max", "ultra"]),
|
|
"gpt-5.6-luna": (272000, ["low", "medium", "high", "xhigh", "max"]),
|
|
}
|
|
|
|
|
|
def value_for(schema: dict[str, Any]) -> Any:
|
|
if "const" in schema:
|
|
return schema["const"]
|
|
if schema.get("enum"):
|
|
return schema["enum"][0]
|
|
if schema.get("oneOf"):
|
|
return value_for(schema["oneOf"][0])
|
|
if schema.get("anyOf"):
|
|
return value_for(schema["anyOf"][0])
|
|
kind = schema.get("type")
|
|
if isinstance(kind, list):
|
|
kind = next((item for item in kind if item != "null"), kind[0])
|
|
if kind == "object" or "properties" in schema:
|
|
props = schema.get("properties", {})
|
|
keys = schema.get("required", list(props))
|
|
return {key: value_for(props[key]) for key in keys if key in props}
|
|
if kind == "array":
|
|
count = max(0, int(schema.get("minItems", 0)))
|
|
return [value_for(schema.get("items", {})) for _ in range(count)]
|
|
if kind == "string" or kind is None:
|
|
if schema.get("pattern") == "^[0-9a-f]{64}$":
|
|
return "0" * 64
|
|
if schema.get("format") in {"uri", "uri-reference"}:
|
|
return "https://example.invalid/evidence"
|
|
value = "fake verified value"
|
|
minimum = int(schema.get("minLength", 0))
|
|
if len(value) < minimum:
|
|
value += "x" * (minimum - len(value))
|
|
return value
|
|
if kind == "integer":
|
|
return max(0, int(schema.get("minimum", 0)))
|
|
if kind == "number":
|
|
return float(max(0, schema.get("minimum", 0)))
|
|
if kind == "boolean":
|
|
return True
|
|
if kind == "null":
|
|
return None
|
|
return "fake verified value"
|
|
|
|
|
|
def extract_schema(prompt: str) -> dict[str, Any] | None:
|
|
markers = (
|
|
"against this JSON Schema:",
|
|
"Return exactly one document satisfying this schema:",
|
|
)
|
|
marker = next((candidate for candidate in markers if candidate in prompt), None)
|
|
if marker is None:
|
|
return None
|
|
tail = prompt.split(marker, 1)[1]
|
|
decoder = json.JSONDecoder()
|
|
for match in re.finditer(r"\{", tail):
|
|
try:
|
|
value, _ = decoder.raw_decode(tail[match.start() :])
|
|
except json.JSONDecodeError:
|
|
continue
|
|
if isinstance(value, dict):
|
|
return value
|
|
return None
|
|
|
|
|
|
def literal_result(prompt: str, cwd: Path) -> dict[str, Any] | None:
|
|
marker = "Perform only the following runtime-generated literal operation."
|
|
if marker not in prompt:
|
|
return None
|
|
tail = prompt.split(marker, 1)[1]
|
|
decoder = json.JSONDecoder()
|
|
task: dict[str, Any] | None = None
|
|
for match in re.finditer(r"\{", tail):
|
|
try:
|
|
value, _ = decoder.raw_decode(tail[match.start() :])
|
|
except json.JSONDecodeError:
|
|
continue
|
|
if isinstance(value, dict) and value.get("operation") in {
|
|
"locate",
|
|
"references",
|
|
"extract",
|
|
"summarize_supplied",
|
|
}:
|
|
task = value
|
|
break
|
|
if task is None:
|
|
return None
|
|
operation = str(task["operation"])
|
|
if operation == "summarize_supplied":
|
|
return {
|
|
"operation": operation,
|
|
"input_sha256": task["input_sha256"],
|
|
"evidence": [],
|
|
"summary_points": ["bounded literal summary"],
|
|
}
|
|
if operation == "extract":
|
|
path = cwd / str(task["path"])
|
|
content = path.read_bytes()
|
|
lines = content.decode("utf-8", errors="replace").splitlines()
|
|
start = int(task["start_line"])
|
|
end = int(task["end_line"])
|
|
evidence = [
|
|
{
|
|
"path": str(task["path"]),
|
|
"sha256": hashlib.sha256(content).hexdigest(),
|
|
"start_line": start,
|
|
"end_line": end,
|
|
"excerpt": "\n".join(lines[start - 1 : end]),
|
|
}
|
|
]
|
|
else:
|
|
query = str(task["needle"] if operation == "locate" else task["symbol"])
|
|
evidence = []
|
|
for raw in task.get("paths", ["."]):
|
|
candidate = (cwd / str(raw)).resolve()
|
|
paths = [candidate] if candidate.is_file() else sorted(candidate.rglob("*"))
|
|
for path in paths:
|
|
if not path.is_file() or path.is_symlink():
|
|
continue
|
|
content = path.read_bytes()
|
|
lines = content.decode("utf-8", errors="replace").splitlines()
|
|
for number, line in enumerate(lines, 1):
|
|
if query not in line:
|
|
continue
|
|
evidence.append(
|
|
{
|
|
"path": path.relative_to(cwd).as_posix(),
|
|
"sha256": hashlib.sha256(content).hexdigest(),
|
|
"start_line": number,
|
|
"end_line": number,
|
|
"excerpt": line,
|
|
}
|
|
)
|
|
break
|
|
if evidence:
|
|
break
|
|
if evidence:
|
|
break
|
|
return {
|
|
"operation": operation,
|
|
"input_sha256": None,
|
|
"evidence": evidence,
|
|
"summary_points": [],
|
|
}
|
|
|
|
|
|
def parse_output_path(args: list[str]) -> Path | None:
|
|
try:
|
|
return Path(args[args.index("--output-last-message") + 1])
|
|
except (ValueError, IndexError):
|
|
return None
|
|
|
|
|
|
def parse_cwd(args: list[str]) -> Path:
|
|
try:
|
|
return Path(args[args.index("-C") + 1]).resolve()
|
|
except (ValueError, IndexError):
|
|
return Path.cwd()
|
|
|
|
|
|
def interactive_rollout(args: list[str]) -> tuple[str, Path]:
|
|
home = Path(os.environ["CODEX_HOME"]).resolve()
|
|
cwd = Path.cwd().resolve()
|
|
resume_index: int | None = None
|
|
if len(args) >= 2 and args[-2] == "resume":
|
|
try:
|
|
uuid.UUID(args[-1])
|
|
except ValueError:
|
|
pass
|
|
else:
|
|
resume_index = len(args) - 2
|
|
if resume_index is not None:
|
|
try:
|
|
thread_id = args[resume_index + 1]
|
|
except IndexError as exc:
|
|
raise RuntimeError("fake resume requires a thread id") from exc
|
|
matches = list((home / "sessions").rglob(f"*{thread_id}.jsonl"))
|
|
if len(matches) != 1:
|
|
raise RuntimeError(f"fake resume could not resolve thread {thread_id}")
|
|
rollout = matches[0]
|
|
with rollout.open("a", encoding="utf-8") as handle:
|
|
handle.write(
|
|
json.dumps(
|
|
{
|
|
"timestamp": dt.datetime.now(dt.UTC).isoformat(),
|
|
"type": "event_msg",
|
|
"payload": {"type": "fake_resume", "thread_id": thread_id},
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
+ "\n"
|
|
)
|
|
else:
|
|
thread_id = str(uuid.uuid4())
|
|
now = dt.datetime.now(dt.UTC)
|
|
directory = home / "sessions" / now.strftime("%Y") / now.strftime("%m") / now.strftime("%d")
|
|
directory.mkdir(parents=True, exist_ok=True)
|
|
rollout = directory / f"rollout-{now.strftime('%Y-%m-%dT%H-%M-%S')}-{thread_id}.jsonl"
|
|
rollout.write_text(
|
|
json.dumps(
|
|
{
|
|
"timestamp": now.isoformat(),
|
|
"type": "session_meta",
|
|
"payload": {
|
|
"id": thread_id,
|
|
"source": "cli",
|
|
"cwd": str(cwd),
|
|
"cli_version": "99.0.0-fake",
|
|
"originator": "codex-tui",
|
|
},
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
with (home / "fake-interactive-invocations.jsonl").open("a", encoding="utf-8") as handle:
|
|
handle.write(
|
|
json.dumps({"args": args, "cwd": str(cwd), "thread_id": thread_id}, sort_keys=True)
|
|
+ "\n"
|
|
)
|
|
return thread_id, rollout
|
|
|
|
|
|
def apply_directives(prompt: str, cwd: Path) -> None:
|
|
sleep = re.search(r"FAKE_SLEEP(?:_SECONDS)?\s*=\s*([0-9.]+)", prompt)
|
|
if sleep:
|
|
time.sleep(min(float(sleep.group(1)), 30.0))
|
|
if "FAKE_ORPHAN_CHILD" in prompt and not (cwd / "fake-orphan.pid").exists():
|
|
child_pid = os.fork()
|
|
if child_pid == 0:
|
|
os.execl(
|
|
sys.executable,
|
|
sys.executable,
|
|
"-c",
|
|
"import time; time.sleep(60)",
|
|
)
|
|
(cwd / "fake-orphan.pid").write_text(str(child_pid), encoding="utf-8")
|
|
for match in re.finditer(r"^FAKE_WRITE\s+([^:]+)::(.*)$", prompt, re.MULTILINE):
|
|
target = (cwd / match.group(1).strip()).resolve()
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text(match.group(2).replace("\\n", "\n") + "\n", encoding="utf-8")
|
|
if "Fix the Inventory.reserve contract completely" in prompt:
|
|
target = cwd / "inventory.py"
|
|
if target.is_file():
|
|
text = target.read_text(encoding="utf-8")
|
|
needle = ' """Reserve positive stock atomically or report that it is unavailable."""\n'
|
|
replacement = (
|
|
needle
|
|
+ " if isinstance(quantity, bool) or not isinstance(quantity, int) or quantity <= 0:\n return False\n"
|
|
)
|
|
if replacement not in text:
|
|
target.write_text(text.replace(needle, replacement), encoding="utf-8")
|
|
|
|
|
|
def final_text(prompt: str, cwd: Path) -> str:
|
|
if "FAKE_EMPTY_RESULT" in prompt:
|
|
return ""
|
|
literal = literal_result(prompt, cwd)
|
|
if literal is not None:
|
|
return json.dumps(literal, sort_keys=True)
|
|
if "FAKE_INVALID_FIRST_RESULT" in prompt and "Repair only the final JSON result" not in prompt:
|
|
return "not json"
|
|
schema = extract_schema(prompt)
|
|
if schema is not None:
|
|
if schema.get("title") == "Reference versus real-browser render review":
|
|
return json.dumps(
|
|
{
|
|
"verdict": "concerns",
|
|
"image_artifacts": [],
|
|
"mismatches": [],
|
|
"blockers": [],
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
return json.dumps(value_for(schema), sort_keys=True)
|
|
markers = re.findall(r"\b(?:EVAL_[A-Z_]+|MMO_[A-Z_]+)\b", prompt)
|
|
return "FAKE_CODEX_OK" + ("\n" + "\n".join(dict.fromkeys(markers)) if markers else "")
|
|
|
|
|
|
def _fake_schema_bundle(args: list[str]) -> int:
|
|
try:
|
|
destination = Path(args[args.index("--out") + 1])
|
|
except (ValueError, IndexError):
|
|
return 2
|
|
destination.mkdir(parents=True, exist_ok=True)
|
|
methods = [
|
|
"thread/start",
|
|
"thread/resume",
|
|
"thread/fork",
|
|
"thread/settings/update",
|
|
"thread/compact/start",
|
|
"turn/start",
|
|
"turn/steer",
|
|
"turn/interrupt",
|
|
"mcpServerStatus/list",
|
|
"mcpServer/tool/call",
|
|
"item/tool/requestUserInput",
|
|
"mcpServer/elicitation/request",
|
|
"item/commandExecution/requestApproval",
|
|
"item/fileChange/requestApproval",
|
|
"item/permissions/requestApproval",
|
|
"applyPatchApproval",
|
|
"execCommandApproval",
|
|
]
|
|
(destination / "ClientRequest.json").write_text(
|
|
json.dumps({"methods": methods}, sort_keys=True), encoding="utf-8"
|
|
)
|
|
(destination / "ServerRequest.json").write_text(
|
|
json.dumps({"methods": methods[10:]}, sort_keys=True), encoding="utf-8"
|
|
)
|
|
contracts = {
|
|
"v2/ThreadStartParams.json": (
|
|
{
|
|
"cwd",
|
|
"sandbox",
|
|
"approvalPolicy",
|
|
"allowProviderModelFallback",
|
|
"ephemeral",
|
|
"historyMode",
|
|
"dynamicTools",
|
|
},
|
|
set(),
|
|
),
|
|
"v2/ThreadResumeParams.json": (
|
|
{"threadId", "path", "cwd", "sandbox", "approvalPolicy", "excludeTurns"},
|
|
{"threadId"},
|
|
),
|
|
"v2/ThreadForkParams.json": (
|
|
{
|
|
"threadId",
|
|
"path",
|
|
"cwd",
|
|
"sandbox",
|
|
"approvalPolicy",
|
|
"ephemeral",
|
|
"deferGoalContinuation",
|
|
"excludeTurns",
|
|
},
|
|
{"threadId"},
|
|
),
|
|
"v2/TurnStartParams.json": (
|
|
{"threadId", "input", "effort", "outputSchema"},
|
|
{"threadId", "input"},
|
|
),
|
|
"v2/TurnSteerParams.json": (
|
|
{"threadId", "expectedTurnId", "input"},
|
|
{"threadId", "expectedTurnId", "input"},
|
|
),
|
|
"v2/TurnInterruptParams.json": (
|
|
{"threadId", "turnId"},
|
|
{"threadId", "turnId"},
|
|
),
|
|
"v2/ThreadSettingsUpdateParams.json": ({"threadId", "effort"}, {"threadId"}),
|
|
"v2/ThreadCompactStartParams.json": ({"threadId"}, {"threadId"}),
|
|
"ToolRequestUserInputResponse.json": ({"answers"}, {"answers"}),
|
|
"McpServerElicitationRequestResponse.json": ({"action", "content", "_meta"}, {"action"}),
|
|
"CommandExecutionRequestApprovalResponse.json": ({"decision"}, {"decision"}),
|
|
"FileChangeRequestApprovalResponse.json": ({"decision"}, {"decision"}),
|
|
"PermissionsRequestApprovalResponse.json": (
|
|
{"permissions", "scope", "strictAutoReview"},
|
|
{"permissions"},
|
|
),
|
|
"ApplyPatchApprovalResponse.json": ({"decision"}, {"decision"}),
|
|
"ExecCommandApprovalResponse.json": ({"decision"}, {"decision"}),
|
|
}
|
|
response_enums = {
|
|
"McpServerElicitationRequestResponse.json": {"accept", "decline", "cancel"},
|
|
"CommandExecutionRequestApprovalResponse.json": {
|
|
"accept",
|
|
"acceptForSession",
|
|
"decline",
|
|
"cancel",
|
|
"allow",
|
|
"deny",
|
|
},
|
|
"FileChangeRequestApprovalResponse.json": {
|
|
"accept",
|
|
"acceptForSession",
|
|
"decline",
|
|
"cancel",
|
|
},
|
|
"PermissionsRequestApprovalResponse.json": {
|
|
"turn",
|
|
"session",
|
|
"read",
|
|
"write",
|
|
"deny",
|
|
"path",
|
|
"glob_pattern",
|
|
"special",
|
|
"root",
|
|
"minimal",
|
|
"project_roots",
|
|
"tmpdir",
|
|
"slash_tmp",
|
|
"unknown",
|
|
},
|
|
"ApplyPatchApprovalResponse.json": {
|
|
"approved",
|
|
"approved_for_session",
|
|
"timed_out",
|
|
"abort",
|
|
"allow",
|
|
"deny",
|
|
},
|
|
"ExecCommandApprovalResponse.json": {
|
|
"approved",
|
|
"approved_for_session",
|
|
"timed_out",
|
|
"abort",
|
|
"allow",
|
|
"deny",
|
|
},
|
|
}
|
|
for relative, (properties, required) in contracts.items():
|
|
path = destination / relative
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(
|
|
json.dumps(
|
|
{
|
|
"type": "object",
|
|
"properties": {key: {} for key in sorted(properties)},
|
|
"required": sorted(required),
|
|
"definitions": {
|
|
"compatibilityEnums": {"enum": sorted(response_enums.get(relative, set()))}
|
|
},
|
|
},
|
|
sort_keys=True,
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
return 0
|
|
|
|
|
|
class _FakeWebSocketPeer:
|
|
"""Small RFC 6455 server peer used by the deterministic app-server fake."""
|
|
|
|
def __init__(self, connection: socket.socket) -> None:
|
|
self.connection = connection
|
|
self.buffer = bytearray()
|
|
self.send_lock = threading.Lock()
|
|
self.closed = False
|
|
self._handshake()
|
|
|
|
def _recv_exact(self, size: int) -> bytes:
|
|
while len(self.buffer) < size:
|
|
chunk = self.connection.recv(max(4096, size - len(self.buffer)))
|
|
if not chunk:
|
|
raise ConnectionError("fake WebSocket client disconnected")
|
|
self.buffer.extend(chunk)
|
|
value = bytes(self.buffer[:size])
|
|
del self.buffer[:size]
|
|
return value
|
|
|
|
def _handshake(self) -> None:
|
|
marker = b"\r\n\r\n"
|
|
while marker not in self.buffer:
|
|
chunk = self.connection.recv(4096)
|
|
if not chunk:
|
|
raise ConnectionError("fake WebSocket handshake closed")
|
|
self.buffer.extend(chunk)
|
|
if len(self.buffer) > 64 * 1024:
|
|
raise ValueError("fake WebSocket handshake is too large")
|
|
raw, trailing = bytes(self.buffer).split(marker, 1)
|
|
self.buffer = bytearray(trailing)
|
|
headers: dict[str, str] = {}
|
|
for line in raw.decode("iso-8859-1").split("\r\n")[1:]:
|
|
if ":" not in line:
|
|
continue
|
|
name, value = line.split(":", 1)
|
|
headers[name.strip().lower()] = value.strip()
|
|
key = headers.get("sec-websocket-key")
|
|
if not key:
|
|
raise ValueError("fake WebSocket handshake has no key")
|
|
digest = base64.b64encode(
|
|
hashlib.sha1( # noqa: S324 - required by RFC 6455
|
|
(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").encode("ascii")
|
|
).digest()
|
|
).decode("ascii")
|
|
self.connection.sendall(
|
|
(
|
|
"HTTP/1.1 101 Switching Protocols\r\n"
|
|
"Upgrade: websocket\r\n"
|
|
"Connection: Upgrade\r\n"
|
|
f"Sec-WebSocket-Accept: {digest}\r\n\r\n"
|
|
).encode("ascii")
|
|
)
|
|
|
|
@staticmethod
|
|
def _frame(opcode: int, payload: bytes) -> bytes:
|
|
first = 0x80 | opcode
|
|
length = len(payload)
|
|
if length < 126:
|
|
return bytes((first, length)) + payload
|
|
if length <= 0xFFFF:
|
|
return bytes((first, 126)) + struct.pack("!H", length) + payload
|
|
return bytes((first, 127)) + struct.pack("!Q", length) + payload
|
|
|
|
def send(self, value: dict[str, Any]) -> None:
|
|
payload = json.dumps(value, ensure_ascii=False, separators=(",", ":")).encode()
|
|
with self.send_lock:
|
|
if self.closed:
|
|
return
|
|
try:
|
|
self.connection.sendall(self._frame(0x1, payload))
|
|
except OSError:
|
|
self.closed = True
|
|
|
|
def receive(self) -> dict[str, Any]:
|
|
fragments = bytearray()
|
|
fragmented = False
|
|
while True:
|
|
first, second = self._recv_exact(2)
|
|
final = bool(first & 0x80)
|
|
if first & 0x70:
|
|
raise ValueError("fake WebSocket client used reserved frame bits")
|
|
opcode = first & 0x0F
|
|
masked = bool(second & 0x80)
|
|
if not masked:
|
|
raise ValueError("fake WebSocket client frame is not masked")
|
|
length = second & 0x7F
|
|
if opcode >= 0x8 and (not final or length > 125):
|
|
raise ValueError("malformed fake WebSocket control frame")
|
|
if length == 126:
|
|
length = struct.unpack("!H", self._recv_exact(2))[0]
|
|
if length < 126:
|
|
raise ValueError("non-minimal fake WebSocket frame length")
|
|
elif length == 127:
|
|
encoded_length = self._recv_exact(8)
|
|
if encoded_length[0] & 0x80:
|
|
raise ValueError("invalid fake WebSocket 64-bit frame length")
|
|
length = struct.unpack("!Q", encoded_length)[0]
|
|
if length <= 0xFFFF:
|
|
raise ValueError("non-minimal fake WebSocket frame length")
|
|
mask = self._recv_exact(4)
|
|
payload = self._recv_exact(length)
|
|
payload = bytes(value ^ mask[index & 3] for index, value in enumerate(payload))
|
|
if opcode == 0x8:
|
|
with self.send_lock:
|
|
self.connection.sendall(self._frame(0x8, payload))
|
|
raise ConnectionError("fake WebSocket client closed")
|
|
if opcode == 0x9:
|
|
with self.send_lock:
|
|
self.connection.sendall(self._frame(0xA, payload))
|
|
continue
|
|
if opcode == 0xA:
|
|
continue
|
|
if opcode == 0x1:
|
|
if fragmented:
|
|
raise ValueError("nested fake WebSocket message")
|
|
fragments.extend(payload)
|
|
fragmented = not final
|
|
elif opcode == 0x0 and fragmented:
|
|
fragments.extend(payload)
|
|
fragmented = not final
|
|
else:
|
|
raise ValueError(f"unsupported fake WebSocket opcode {opcode}")
|
|
if not fragmented:
|
|
value = json.loads(fragments.decode())
|
|
if not isinstance(value, dict):
|
|
raise ValueError("fake app-server request must be an object")
|
|
return value
|
|
|
|
def close(self) -> None:
|
|
self.closed = True
|
|
try:
|
|
self.connection.close()
|
|
except OSError:
|
|
pass
|
|
|
|
|
|
def _fake_app_server(args: list[str]) -> int:
|
|
home = Path(os.environ["CODEX_HOME"]).resolve()
|
|
state_lock = threading.Lock()
|
|
peers_lock = threading.Lock()
|
|
peers: list[_FakeWebSocketPeer] = []
|
|
threads: dict[str, dict[str, Any]] = {}
|
|
active: dict[str, dict[str, Any]] = {}
|
|
pending_requests: dict[str, tuple[str, threading.Event]] = {}
|
|
|
|
def emit(value: dict[str, Any]) -> None:
|
|
with peers_lock:
|
|
current = list(peers)
|
|
for peer in current:
|
|
peer.send(value)
|
|
|
|
def response(peer: _FakeWebSocketPeer, request_id: Any, result: Any) -> None:
|
|
peer.send({"id": request_id, "result": result})
|
|
|
|
def error(peer: _FakeWebSocketPeer, request_id: Any, code: int, message: str) -> None:
|
|
peer.send(
|
|
{
|
|
"id": request_id,
|
|
"error": {"code": code, "message": message},
|
|
}
|
|
)
|
|
|
|
def new_rollout(
|
|
cwd: Path,
|
|
*,
|
|
source_path: Path | None = None,
|
|
parent_thread_id: str | None = None,
|
|
) -> dict[str, Any]:
|
|
thread_id = str(uuid.uuid4())
|
|
now = dt.datetime.now(dt.UTC)
|
|
directory = home / "sessions" / now.strftime("%Y") / now.strftime("%m") / now.strftime("%d")
|
|
directory.mkdir(parents=True, exist_ok=True)
|
|
path = directory / f"rollout-{now.strftime('%Y-%m-%dT%H-%M-%S')}-{thread_id}.jsonl"
|
|
turns: list[dict[str, Any]] = []
|
|
prompt_history: list[str] = []
|
|
if source_path is not None and source_path.is_file():
|
|
for line in source_path.read_text(encoding="utf-8", errors="replace").splitlines()[1:]:
|
|
try:
|
|
row = json.loads(line)
|
|
except json.JSONDecodeError:
|
|
continue
|
|
if row.get("type") == "fake_turn" and isinstance(row.get("turn"), dict):
|
|
turns.append(row["turn"])
|
|
elif row.get("type") == "fake_prompt" and isinstance(row.get("text"), str):
|
|
prompt_history.append(row["text"])
|
|
path.write_text(
|
|
json.dumps(
|
|
{
|
|
"timestamp": now.isoformat(),
|
|
"type": "session_meta",
|
|
"payload": {
|
|
"id": thread_id,
|
|
"source": "appServer",
|
|
"cwd": str(cwd),
|
|
"cli_version": "99.0.0-fake",
|
|
"parent_thread_id": parent_thread_id,
|
|
},
|
|
},
|
|
sort_keys=True,
|
|
)
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
for turn in turns:
|
|
with path.open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps({"type": "fake_turn", "turn": turn}) + "\n")
|
|
for historical_prompt in prompt_history:
|
|
with path.open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps({"type": "fake_prompt", "text": historical_prompt}) + "\n")
|
|
value = {
|
|
"id": thread_id,
|
|
"sessionId": thread_id,
|
|
"path": str(path),
|
|
"cwd": str(cwd),
|
|
"createdAt": int(now.timestamp()),
|
|
"updatedAt": int(now.timestamp()),
|
|
"source": "vscode",
|
|
"threadSource": None,
|
|
"ephemeral": False,
|
|
"parentThreadId": parent_thread_id,
|
|
"forkedFromId": None,
|
|
"agentRole": None,
|
|
"agentNickname": None,
|
|
"turns": turns,
|
|
"prompt_history": prompt_history,
|
|
"status": {"type": "idle"},
|
|
"goal": None,
|
|
"archived": False,
|
|
}
|
|
threads[thread_id] = value
|
|
return value
|
|
|
|
def load_thread(thread_id: str, path_value: Any = None) -> dict[str, Any] | None:
|
|
if thread_id in threads:
|
|
return threads[thread_id]
|
|
candidates = [Path(path_value)] if isinstance(path_value, str) else []
|
|
candidates.extend((home / "sessions").rglob(f"*{thread_id}.jsonl"))
|
|
matches = [path for path in candidates if path.is_file()]
|
|
if not matches:
|
|
return None
|
|
path = matches[0].resolve()
|
|
turns: list[dict[str, Any]] = []
|
|
prompt_history: list[str] = []
|
|
rows = path.read_text(encoding="utf-8", errors="replace").splitlines()
|
|
parent_thread_id = None
|
|
if rows:
|
|
try:
|
|
metadata = json.loads(rows[0])
|
|
except json.JSONDecodeError:
|
|
metadata = None
|
|
payload = metadata.get("payload") if isinstance(metadata, dict) else None
|
|
if isinstance(payload, dict) and isinstance(payload.get("parent_thread_id"), str):
|
|
parent_thread_id = payload["parent_thread_id"]
|
|
for line in rows[1:]:
|
|
try:
|
|
row = json.loads(line)
|
|
except json.JSONDecodeError:
|
|
continue
|
|
if row.get("type") == "fake_turn" and isinstance(row.get("turn"), dict):
|
|
turns.append(row["turn"])
|
|
elif row.get("type") == "fake_prompt" and isinstance(row.get("text"), str):
|
|
prompt_history.append(row["text"])
|
|
value = {
|
|
"id": thread_id,
|
|
"sessionId": thread_id,
|
|
"path": str(path),
|
|
"cwd": str(Path.cwd().resolve()),
|
|
"createdAt": int(path.stat().st_mtime),
|
|
"updatedAt": int(path.stat().st_mtime),
|
|
"source": "vscode",
|
|
"threadSource": None,
|
|
"ephemeral": False,
|
|
"parentThreadId": parent_thread_id,
|
|
"forkedFromId": None,
|
|
"agentRole": None,
|
|
"agentNickname": None,
|
|
"turns": turns,
|
|
"prompt_history": prompt_history,
|
|
"status": {"type": "idle"},
|
|
"goal": None,
|
|
}
|
|
threads[thread_id] = value
|
|
return value
|
|
|
|
def run_turn(
|
|
thread: dict[str, Any], turn_id: str, prompt_parts: list[str], output_schema: Any
|
|
) -> None:
|
|
turn_prompt = "\n".join(prompt_parts)
|
|
prompt = turn_prompt
|
|
interrupt = active[thread["id"]]["interrupt"]
|
|
sleep_match = re.search(r"FAKE_SLEEP(?:_SECONDS)?\s*=\s*([0-9.]+)", prompt)
|
|
if sleep_match:
|
|
deadline = time.monotonic() + min(float(sleep_match.group(1)), 30.0)
|
|
while time.monotonic() < deadline and not interrupt.wait(0.02):
|
|
pass
|
|
if "FAKE_REQUEST_USER_INPUT" in prompt and not interrupt.is_set():
|
|
request_id = f"fake-input-{turn_id}"
|
|
wait = threading.Event()
|
|
pending_requests[request_id] = (thread["id"], wait)
|
|
emit(
|
|
{
|
|
"id": request_id,
|
|
"method": "item/tool/requestUserInput",
|
|
"params": {
|
|
"threadId": thread["id"],
|
|
"turnId": turn_id,
|
|
"questions": [],
|
|
},
|
|
}
|
|
)
|
|
while not wait.wait(0.02) and not interrupt.is_set():
|
|
pass
|
|
if "FAKE_REQUEST_COMMAND_APPROVAL" in prompt and not interrupt.is_set():
|
|
request_id = f"fake-approval-{turn_id}"
|
|
wait = threading.Event()
|
|
pending_requests[request_id] = (thread["id"], wait)
|
|
emit(
|
|
{
|
|
"id": request_id,
|
|
"method": "item/commandExecution/requestApproval",
|
|
"params": {
|
|
"threadId": thread["id"],
|
|
"turnId": turn_id,
|
|
"itemId": f"fake-command-{turn_id}",
|
|
"reason": "synthetic approval request",
|
|
},
|
|
}
|
|
)
|
|
while not wait.wait(0.02) and not interrupt.is_set():
|
|
pass
|
|
with state_lock:
|
|
prompt = "\n".join(thread.get("prompt_history", []))
|
|
if "FAKE_APP_SERVER_CRASH_ONCE" in prompt:
|
|
marker = home / "fake-app-server-crashed-once"
|
|
if not marker.exists():
|
|
marker.write_text("crashed\n", encoding="utf-8")
|
|
os._exit(70)
|
|
if interrupt.is_set():
|
|
status = "interrupted"
|
|
text = ""
|
|
elif (
|
|
"FAKE_PROVIDER_USAGE_LIMIT" in prompt
|
|
and not (
|
|
"FAKE_PROVIDER_USAGE_LIMIT_ONCE" in prompt
|
|
and any(
|
|
isinstance(prior.get("error"), dict)
|
|
and "usage limit" in str(prior["error"].get("message", "")).lower()
|
|
for prior in thread.get("turns", [])
|
|
if isinstance(prior, dict)
|
|
)
|
|
)
|
|
) or "FAKE_PROVIDER_BAD_REQUEST" in prompt:
|
|
status = "failed"
|
|
text = ""
|
|
else:
|
|
apply_directives(
|
|
re.sub(r"FAKE_SLEEP(?:_SECONDS)?\s*=\s*[0-9.]+", "", prompt), Path.cwd()
|
|
)
|
|
text = (
|
|
json.dumps(value_for(output_schema), sort_keys=True)
|
|
if isinstance(output_schema, dict)
|
|
else final_text(prompt, Path.cwd())
|
|
)
|
|
status = "completed"
|
|
turn: dict[str, Any] = {
|
|
"id": turn_id,
|
|
"status": status,
|
|
"items": ([{"type": "agentMessage", "text": text}] if text else []),
|
|
}
|
|
if status == "failed":
|
|
turn["error"] = (
|
|
{
|
|
"message": "Provider rejected the request as invalid",
|
|
"codexErrorInfo": "badRequest",
|
|
}
|
|
if "FAKE_PROVIDER_BAD_REQUEST" in prompt
|
|
else {
|
|
"message": (
|
|
"Provider usage limit reached; limit will reset at 2026-08-22 05:24:28"
|
|
)
|
|
}
|
|
)
|
|
multiplier = len(thread["turns"]) + 1
|
|
total_usage = {
|
|
"inputTokens": 101 * multiplier,
|
|
"outputTokens": 23 * multiplier,
|
|
"cachedInputTokens": 7 * multiplier,
|
|
"cacheWriteInputTokens": 3 * multiplier,
|
|
"reasoningOutputTokens": 11 * multiplier,
|
|
"totalTokens": 124 * multiplier,
|
|
}
|
|
emit(
|
|
{
|
|
"method": "thread/tokenUsage/updated",
|
|
"params": {
|
|
"threadId": thread["id"],
|
|
"turnId": turn_id,
|
|
"tokenUsage": {"total": total_usage, "last": total_usage},
|
|
},
|
|
}
|
|
)
|
|
if any(
|
|
marker in prompt
|
|
for marker in (
|
|
"FAKE_GOAL_COMPLETE_BEFORE_TURN",
|
|
"FAKE_GOAL_BUDGET_LIMIT_BEFORE_TURN",
|
|
)
|
|
):
|
|
# The real worker starts the first turn while its goal is paused,
|
|
# then activates the goal. Do not make these ordering fixtures
|
|
# depend on host scheduling speed: wait until that activation is
|
|
# observable before publishing the requested terminal goal state.
|
|
deadline = time.monotonic() + 5.0
|
|
while time.monotonic() < deadline:
|
|
with state_lock:
|
|
goal = thread.get("goal")
|
|
if isinstance(goal, dict) and goal.get("status") == "active":
|
|
break
|
|
time.sleep(0.01)
|
|
with state_lock:
|
|
goal = thread.get("goal")
|
|
completed_goal = None
|
|
if (
|
|
"FAKE_GOAL_COMPLETE_BEFORE_TURN" in prompt
|
|
and isinstance(goal, dict)
|
|
and goal.get("status") == "active"
|
|
):
|
|
goal["status"] = "complete"
|
|
goal["tokensUsed"] = total_usage["totalTokens"]
|
|
goal["timeUsedSeconds"] = 0
|
|
completed_goal = dict(goal)
|
|
elif (
|
|
"FAKE_GOAL_BUDGET_LIMIT_BEFORE_TURN" in prompt
|
|
and isinstance(goal, dict)
|
|
and goal.get("status") == "active"
|
|
):
|
|
goal["status"] = "budgetLimited"
|
|
goal["tokensUsed"] = total_usage["totalTokens"]
|
|
goal["timeUsedSeconds"] = 0
|
|
completed_goal = dict(goal)
|
|
if completed_goal is not None:
|
|
emit(
|
|
{
|
|
"method": "thread/goal/updated",
|
|
"params": {"threadId": thread["id"], "goal": completed_goal},
|
|
}
|
|
)
|
|
time.sleep(0.75)
|
|
thread["turns"].append(turn)
|
|
with Path(thread["path"]).open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps({"type": "fake_turn", "turn": turn}, sort_keys=True) + "\n")
|
|
crash_after_persist = "FAKE_APP_SERVER_CRASH_AFTER_PERSIST_ONCE" in prompt
|
|
crash_during_finalization = (
|
|
"FAKE_APP_SERVER_CRASH_DURING_FINALIZATION_ONCE" in prompt
|
|
and "Terminal serialization turn" in turn_prompt
|
|
)
|
|
if crash_after_persist or crash_during_finalization:
|
|
marker = home / (
|
|
"fake-app-server-crashed-during-finalization-once"
|
|
if crash_during_finalization
|
|
else "fake-app-server-crashed-after-persist-once"
|
|
)
|
|
if not marker.exists():
|
|
marker.write_text("crashed\n", encoding="utf-8")
|
|
os._exit(71)
|
|
emit(
|
|
{
|
|
"method": "turn/completed",
|
|
"params": {"threadId": thread["id"], "turn": turn},
|
|
}
|
|
)
|
|
with state_lock:
|
|
active.pop(thread["id"], None)
|
|
thread["status"] = {"type": "idle"}
|
|
goal = thread.get("goal")
|
|
if status == "completed" and isinstance(goal, dict) and goal.get("status") == "active":
|
|
goal["status"] = "complete"
|
|
goal["tokensUsed"] = total_usage["totalTokens"]
|
|
goal["timeUsedSeconds"] = 0
|
|
completed_goal = dict(goal)
|
|
else:
|
|
completed_goal = None
|
|
emit(
|
|
{
|
|
"method": "thread/status/changed",
|
|
"params": {"threadId": thread["id"], "status": {"type": "idle"}},
|
|
}
|
|
)
|
|
if completed_goal is not None:
|
|
emit(
|
|
{
|
|
"method": "thread/goal/updated",
|
|
"params": {"threadId": thread["id"], "goal": completed_goal},
|
|
}
|
|
)
|
|
|
|
def handle_message(peer: _FakeWebSocketPeer, message: dict[str, Any]) -> None:
|
|
if "jsonrpc" in message:
|
|
raise ValueError("Codex 0.149 app-server messages do not carry jsonrpc")
|
|
request_id = message.get("id")
|
|
method = message.get("method")
|
|
raw_params = message.get("params")
|
|
params: dict[str, Any] = raw_params if isinstance(raw_params, dict) else {}
|
|
if method == "initialize":
|
|
initialize_delay = os.environ.get("FAKE_CODEX_APP_SERVER_INITIALIZE_DELAY")
|
|
if initialize_delay:
|
|
time.sleep(min(float(initialize_delay), 30.0))
|
|
response(
|
|
peer,
|
|
request_id,
|
|
{"serverInfo": {"name": "fake-codex", "version": "99.0.0"}},
|
|
)
|
|
elif method == "initialized":
|
|
return
|
|
elif method == "mcpServerStatus/list":
|
|
response(peer, request_id, {"data": [], "nextCursor": None})
|
|
elif method == "mcpServer/tool/call":
|
|
response(
|
|
peer,
|
|
request_id,
|
|
{"content": [{"type": "text", "text": "fake MCP tool result"}]},
|
|
)
|
|
elif method == "thread/start":
|
|
started_thread = new_rollout(Path(str(params.get("cwd") or Path.cwd())).resolve())
|
|
response(peer, request_id, {"thread": started_thread})
|
|
emit(
|
|
{
|
|
"method": "thread/started",
|
|
"params": {"thread": started_thread},
|
|
}
|
|
)
|
|
elif method == "thread/resume":
|
|
thread_id = str(params.get("threadId", ""))
|
|
resumed_thread = load_thread(thread_id, params.get("path"))
|
|
if resumed_thread is None:
|
|
error(peer, request_id, -32001, "thread not found")
|
|
else:
|
|
response(peer, request_id, {"thread": resumed_thread})
|
|
elif method == "thread/fork":
|
|
source_id = str(params.get("threadId", ""))
|
|
source = load_thread(source_id, params.get("path"))
|
|
if source is None:
|
|
error(peer, request_id, -32001, "source thread not found")
|
|
else:
|
|
forked_thread = new_rollout(
|
|
Path(str(params.get("cwd") or Path.cwd())).resolve(),
|
|
source_path=Path(source["path"]),
|
|
parent_thread_id=source_id,
|
|
)
|
|
response(peer, request_id, {"thread": forked_thread})
|
|
elif method == "thread/read":
|
|
read_thread = load_thread(str(params.get("threadId", "")))
|
|
if read_thread is None:
|
|
error(peer, request_id, -32001, "thread not found")
|
|
else:
|
|
response(peer, request_id, {"thread": read_thread})
|
|
elif method == "thread/turns/list":
|
|
listed_thread = load_thread(str(params.get("threadId", "")))
|
|
if listed_thread is None:
|
|
error(peer, request_id, -32001, "thread not found")
|
|
else:
|
|
response(
|
|
peer,
|
|
request_id,
|
|
{"data": list(listed_thread["turns"]), "nextCursor": None},
|
|
)
|
|
elif method == "thread/list":
|
|
for path in (home / "sessions").rglob("*.jsonl"):
|
|
try:
|
|
first = path.read_text(encoding="utf-8", errors="replace").splitlines()[0]
|
|
metadata = json.loads(first)
|
|
except (IndexError, OSError, json.JSONDecodeError):
|
|
continue
|
|
payload = metadata.get("payload") if isinstance(metadata, dict) else None
|
|
discovered_thread_id = payload.get("id") if isinstance(payload, dict) else None
|
|
if isinstance(discovered_thread_id, str) and discovered_thread_id not in threads:
|
|
load_thread(discovered_thread_id, str(path))
|
|
ancestor = params.get("ancestorThreadId")
|
|
archived = params.get("archived")
|
|
data = [
|
|
value
|
|
for value in threads.values()
|
|
if ancestor is None or value.get("parentThreadId") == ancestor
|
|
if archived is None or value.get("archived", False) is archived
|
|
]
|
|
response(peer, request_id, {"data": data, "nextCursor": None})
|
|
elif method == "thread/archive":
|
|
archived_thread = load_thread(str(params.get("threadId", "")))
|
|
if archived_thread is None:
|
|
error(peer, request_id, -32001, "thread not found")
|
|
else:
|
|
archived_thread["archived"] = True
|
|
response(peer, request_id, {})
|
|
elif method == "thread/goal/set":
|
|
objective = params.get("objective")
|
|
if isinstance(objective, str) and len(objective) > 4000:
|
|
error(
|
|
peer,
|
|
request_id,
|
|
-32602,
|
|
"goal objective must be at most 4000 characters",
|
|
)
|
|
return
|
|
goal_thread = load_thread(str(params.get("threadId", "")))
|
|
if goal_thread is None:
|
|
error(peer, request_id, -32001, "thread not found")
|
|
return
|
|
with state_lock:
|
|
existing = goal_thread.get("goal")
|
|
previous_goal_status = (
|
|
existing.get("status") if isinstance(existing, dict) else None
|
|
)
|
|
goal = (
|
|
dict(existing)
|
|
if isinstance(existing, dict)
|
|
else {
|
|
"objective": "",
|
|
"status": "paused",
|
|
"tokenBudget": None,
|
|
"tokensUsed": 0,
|
|
"timeUsedSeconds": 0,
|
|
}
|
|
)
|
|
if "objective" in params:
|
|
goal["objective"] = params["objective"]
|
|
if "tokenBudget" in params:
|
|
goal["tokenBudget"] = params["tokenBudget"]
|
|
if "status" in params:
|
|
goal["status"] = params["status"]
|
|
auto_continue = False
|
|
if goal["status"] == "active" and goal_thread["id"] not in active:
|
|
turns = goal_thread.get("turns", [])
|
|
last_turn = turns[-1] if turns and isinstance(turns[-1], dict) else None
|
|
auto_continue = bool(
|
|
(
|
|
isinstance(last_turn, dict)
|
|
and last_turn.get("status") in {"failed", "interrupted"}
|
|
)
|
|
or previous_goal_status in {"blocked", "budgetLimited", "usageLimited"}
|
|
)
|
|
if not auto_continue:
|
|
# Ordinary fake turns stand in for a model that marks
|
|
# its goal complete. Keep that baseline behavior while
|
|
# exercising real automatic continuation after an
|
|
# interrupted or retryable failed turn.
|
|
goal["status"] = "complete"
|
|
goal_thread["goal"] = goal
|
|
response(peer, request_id, {"goal": goal})
|
|
emit(
|
|
{
|
|
"method": "thread/goal/updated",
|
|
"params": {"threadId": goal_thread["id"], "goal": goal},
|
|
}
|
|
)
|
|
if auto_continue:
|
|
# Codex goals normally continue automatically. Model that
|
|
# protocol behavior so recovery tests cannot pass merely
|
|
# because the stand-in marks an idle active goal complete.
|
|
turn_id = str(uuid.uuid4())
|
|
prompt_parts = ["Continue the active goal from retained thread context."]
|
|
goal_thread.setdefault("prompt_history", []).extend(prompt_parts)
|
|
with Path(goal_thread["path"]).open("a", encoding="utf-8") as handle:
|
|
handle.write(
|
|
json.dumps({"type": "fake_prompt", "text": prompt_parts[0]}) + "\n"
|
|
)
|
|
active[goal_thread["id"]] = {
|
|
"turn_id": turn_id,
|
|
"interrupt": threading.Event(),
|
|
"prompt_parts": prompt_parts,
|
|
}
|
|
goal_thread["status"] = {"type": "active"}
|
|
emit(
|
|
{
|
|
"method": "turn/started",
|
|
"params": {
|
|
"threadId": goal_thread["id"],
|
|
"turn": {"id": turn_id, "status": "inProgress", "items": []},
|
|
},
|
|
}
|
|
)
|
|
emit(
|
|
{
|
|
"method": "thread/status/changed",
|
|
"params": {
|
|
"threadId": goal_thread["id"],
|
|
"status": {"type": "active"},
|
|
},
|
|
}
|
|
)
|
|
threading.Thread(
|
|
target=run_turn,
|
|
args=(goal_thread, turn_id, prompt_parts, None),
|
|
daemon=True,
|
|
).start()
|
|
elif method == "turn/start":
|
|
turn_thread = load_thread(str(params.get("threadId", "")))
|
|
if turn_thread is None:
|
|
error(peer, request_id, -32001, "thread not found")
|
|
return
|
|
turn_id = str(uuid.uuid4())
|
|
prompt_parts = [
|
|
str(item.get("text", ""))
|
|
for item in params.get("input", [])
|
|
if isinstance(item, dict) and item.get("type") == "text"
|
|
]
|
|
current_prompt = "\n".join(prompt_parts)
|
|
turn_thread.setdefault("prompt_history", []).append(current_prompt)
|
|
with Path(turn_thread["path"]).open("a", encoding="utf-8") as handle:
|
|
handle.write(json.dumps({"type": "fake_prompt", "text": current_prompt}) + "\n")
|
|
active[turn_thread["id"]] = {
|
|
"turn_id": turn_id,
|
|
"interrupt": threading.Event(),
|
|
"prompt_parts": prompt_parts,
|
|
}
|
|
turn_thread["status"] = {"type": "active"}
|
|
started_message = {
|
|
"method": "turn/started",
|
|
"params": {
|
|
"threadId": turn_thread["id"],
|
|
"turn": {"id": turn_id, "status": "inProgress", "items": []},
|
|
},
|
|
}
|
|
if "FAKE_NOTIFY_BEFORE_RESPONSE" in current_prompt:
|
|
emit(started_message)
|
|
response(
|
|
peer,
|
|
request_id,
|
|
{"turn": {"id": turn_id, "status": "inProgress", "items": []}},
|
|
)
|
|
if "FAKE_NOTIFY_BEFORE_RESPONSE" not in current_prompt:
|
|
emit(started_message)
|
|
emit(
|
|
{
|
|
"method": "thread/status/changed",
|
|
"params": {
|
|
"threadId": turn_thread["id"],
|
|
"status": {"type": "active"},
|
|
},
|
|
}
|
|
)
|
|
threading.Thread(
|
|
target=run_turn,
|
|
args=(turn_thread, turn_id, prompt_parts, params.get("outputSchema")),
|
|
daemon=True,
|
|
).start()
|
|
elif method == "turn/steer":
|
|
current = active.get(str(params.get("threadId", "")))
|
|
if current is None or current["turn_id"] != params.get("expectedTurnId"):
|
|
error(peer, request_id, -32002, "active turn mismatch")
|
|
else:
|
|
additions = [
|
|
str(item.get("text", ""))
|
|
for item in params.get("input", [])
|
|
if isinstance(item, dict) and item.get("type") == "text"
|
|
]
|
|
current["prompt_parts"].extend(additions)
|
|
steered_thread = load_thread(str(params.get("threadId", "")))
|
|
if steered_thread is not None:
|
|
steered_thread.setdefault("prompt_history", []).extend(additions)
|
|
with Path(steered_thread["path"]).open("a", encoding="utf-8") as handle:
|
|
for addition in additions:
|
|
handle.write(
|
|
json.dumps({"type": "fake_prompt", "text": addition}) + "\n"
|
|
)
|
|
response(peer, request_id, {"turnId": current["turn_id"]})
|
|
elif method == "turn/interrupt":
|
|
current = active.get(str(params.get("threadId", "")))
|
|
if current is not None and current["turn_id"] == params.get("turnId"):
|
|
current["interrupt"].set()
|
|
response(peer, request_id, {})
|
|
elif method in {"thread/settings/update", "thread/compact/start"}:
|
|
response(peer, request_id, {})
|
|
elif request_id is not None and method is None:
|
|
pending = pending_requests.pop(str(request_id), None)
|
|
if pending is not None:
|
|
pending[1].set()
|
|
elif request_id is not None:
|
|
error(peer, request_id, -32601, f"method not found: {method}")
|
|
|
|
def serve_peer(connection: socket.socket) -> None:
|
|
peer: _FakeWebSocketPeer | None = None
|
|
try:
|
|
peer = _FakeWebSocketPeer(connection)
|
|
with peers_lock:
|
|
peers.append(peer)
|
|
while True:
|
|
handle_message(peer, peer.receive())
|
|
except (ConnectionError, OSError, ValueError, json.JSONDecodeError):
|
|
pass
|
|
finally:
|
|
if peer is not None:
|
|
with peers_lock:
|
|
if peer in peers:
|
|
peers.remove(peer)
|
|
peer.close()
|
|
else:
|
|
connection.close()
|
|
|
|
try:
|
|
listen_value = args[args.index("--listen") + 1]
|
|
except (ValueError, IndexError):
|
|
print("fake app-server requires --listen unix://PATH", file=sys.stderr)
|
|
return 2
|
|
if not listen_value.startswith("unix://"):
|
|
print("fake app-server supports only a Unix listener", file=sys.stderr)
|
|
return 2
|
|
socket_path = Path(listen_value.removeprefix("unix://"))
|
|
socket_path.parent.mkdir(parents=True, exist_ok=True)
|
|
listener = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
listener.bind(str(socket_path))
|
|
os.chmod(socket_path, 0o600)
|
|
listener.listen(16)
|
|
while True:
|
|
connection, _address = listener.accept()
|
|
threading.Thread(target=serve_peer, args=(connection,), daemon=True).start()
|
|
|
|
|
|
def main() -> int:
|
|
args = sys.argv[1:]
|
|
if args and args[0] in {"--version", "version"}:
|
|
print("codex-cli 0.149.0")
|
|
return 0
|
|
if args[:2] == ["debug", "models"]:
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"models": [
|
|
{
|
|
"slug": item,
|
|
"display_name": item,
|
|
"context_window": MODEL_METADATA.get(item, (272000, []))[0],
|
|
"input_modalities": ["text", "image"],
|
|
"supported_reasoning_levels": [
|
|
{"effort": value}
|
|
for value in MODEL_METADATA.get(
|
|
item,
|
|
(272000, ["low", "medium", "high", "xhigh"]),
|
|
)[1]
|
|
],
|
|
}
|
|
for item in MODELS
|
|
]
|
|
}
|
|
)
|
|
)
|
|
return 0
|
|
if args[:2] == ["login", "status"]:
|
|
print("Logged in (fake)")
|
|
return 0
|
|
if args and args[0] == "login":
|
|
print("Login complete (fake)")
|
|
return 0
|
|
if "app-server" in args:
|
|
app_index = args.index("app-server")
|
|
app_args = args[app_index + 1 :]
|
|
if app_args and app_args[0] == "generate-json-schema":
|
|
return _fake_schema_bundle(app_args[1:])
|
|
return _fake_app_server(app_args)
|
|
if args and args[0] == "exec":
|
|
# Codex 0.149's shared --image argument is variadic (num_args = 1..).
|
|
# A bare '-' before the option terminator is therefore an image path,
|
|
# not the prompt-from-stdin operand.
|
|
option_end = args.index("--") if "--" in args else len(args)
|
|
if "--image" in args and "-" in args[args.index("--image") + 1 : option_end]:
|
|
print("stdin sentinel was consumed by variadic --image", file=sys.stderr)
|
|
return 2
|
|
prompt = sys.stdin.read()
|
|
cwd = parse_cwd(args)
|
|
apply_directives(prompt, cwd)
|
|
exit_match = re.search(r"FAKE_EXIT\s*=\s*(\d+)", prompt)
|
|
code = int(exit_match.group(1)) if exit_match else 0
|
|
output = parse_output_path(args)
|
|
text = final_text(prompt, cwd)
|
|
if output is not None and code == 0:
|
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
output.write_text(text + "\n", encoding="utf-8")
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"type": "turn.completed",
|
|
"usage": {
|
|
"input_tokens": 101,
|
|
"output_tokens": 23,
|
|
"cached_input_tokens": 7,
|
|
"cache_write_input_tokens": 3,
|
|
"reasoning_output_tokens": 11,
|
|
},
|
|
"retry_count": 0,
|
|
}
|
|
)
|
|
)
|
|
if code:
|
|
print("forced fake failure", file=sys.stderr)
|
|
return code
|
|
# Interactive mode is intentionally simple but permits launch tests.
|
|
interactive_rollout(args)
|
|
if os.environ.get("FAKE_TUI_PROBE") == "1":
|
|
resized = False
|
|
|
|
def on_resize(_signum: int, _frame: object) -> None:
|
|
nonlocal resized
|
|
resized = True
|
|
|
|
signal.signal(signal.SIGWINCH, on_resize)
|
|
|
|
def state(event: str) -> dict[str, object]:
|
|
try:
|
|
size = os.get_terminal_size(sys.stdin.fileno())
|
|
columns, lines = size.columns, size.lines
|
|
except OSError:
|
|
columns, lines = -1, -1
|
|
try:
|
|
foreground_pgrp = os.tcgetpgrp(sys.stdin.fileno())
|
|
except OSError:
|
|
foreground_pgrp = -1
|
|
return {
|
|
"event": event,
|
|
"stdin_isatty": sys.stdin.isatty(),
|
|
"stdout_isatty": sys.stdout.isatty(),
|
|
"stderr_isatty": sys.stderr.isatty(),
|
|
"no_color": os.environ.get("NO_COLOR"),
|
|
"term": os.environ.get("TERM"),
|
|
"pgrp": os.getpgrp(),
|
|
"foreground_pgrp": foreground_pgrp,
|
|
"columns": columns,
|
|
"lines": lines,
|
|
}
|
|
|
|
# Exercise raw ANSI passthrough in addition to environment inspection.
|
|
# A wrapper that injects NO_COLOR or captures/re-emits output can make
|
|
# the real Codex TUI appear monochrome or corrupt its control stream.
|
|
print("\x1b[32mFAKE_TUI_COLOR\x1b[0m", flush=True)
|
|
|
|
# Simulate a full-screen TUI entering a modified terminal mode and then
|
|
# exiting without restoring it. The MMO launcher must return the user's
|
|
# terminal to the attributes captured before Codex started.
|
|
attributes = termios.tcgetattr(sys.stdin.fileno())
|
|
attributes[3] &= ~termios.ECHO
|
|
termios.tcsetattr(sys.stdin.fileno(), termios.TCSANOW, attributes)
|
|
print(json.dumps(state("ready"), sort_keys=True), flush=True)
|
|
deadline = time.monotonic() + 5.0
|
|
while not resized and time.monotonic() < deadline:
|
|
time.sleep(0.02)
|
|
print(
|
|
json.dumps(state("resized" if resized else "resize_timeout"), sort_keys=True),
|
|
flush=True,
|
|
)
|
|
return 0
|
|
print("FAKE_CODEX_INTERACTIVE")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|