😏
This commit is contained in:
+181
@@ -0,0 +1,181 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import tempfile
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from unittest import mock
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FAKE_CODEX = ROOT / "tests" / "helpers" / "fake_codex.py"
|
||||
FAKE_SWITCHYARD = ROOT / "tests" / "helpers" / "fake_switchyard.py"
|
||||
|
||||
|
||||
def root_thread_binding(thread_id: str | None) -> dict[str, object]:
|
||||
"""Return one internally consistent root-thread lineage for state-fixture tests."""
|
||||
|
||||
if thread_id is None:
|
||||
return {
|
||||
"root_thread_id": None,
|
||||
"root_thread_generation": 0,
|
||||
"root_thread_lineage": [],
|
||||
"root_thread_transition": None,
|
||||
}
|
||||
return {
|
||||
"root_thread_id": thread_id,
|
||||
"root_thread_generation": 1,
|
||||
"root_thread_lineage": [
|
||||
{
|
||||
"generation": 1,
|
||||
"thread_id": thread_id,
|
||||
"codex_session_id": thread_id,
|
||||
"adopted_at": "2000-01-01T00:00:00+00:00",
|
||||
"reason": "test_fixture",
|
||||
}
|
||||
],
|
||||
"root_thread_transition": None,
|
||||
}
|
||||
|
||||
|
||||
def create_access_lab_session(
|
||||
*, cwd: Path, profile: str | Path = "access-efficient-escalation-lab"
|
||||
) -> dict[str, Any]:
|
||||
"""Create the local-first fixture without depending on a host llama.cpp process."""
|
||||
|
||||
import mmo_runtime
|
||||
|
||||
real_availability = mmo_runtime.route_availability
|
||||
|
||||
def available_local_route(snapshot: Mapping[str, Any]) -> dict[str, dict[str, Any]]:
|
||||
availability = real_availability(snapshot)
|
||||
availability["llama_cpp_local_openai_chat"] = {
|
||||
"available": True,
|
||||
"selected_credential_env": None,
|
||||
"reason": None,
|
||||
}
|
||||
return availability
|
||||
|
||||
with mock.patch.object(
|
||||
mmo_runtime,
|
||||
"route_availability",
|
||||
side_effect=available_local_route,
|
||||
):
|
||||
return mmo_runtime.create_session(profile=profile, cwd=cwd)
|
||||
|
||||
|
||||
class RuntimeSandbox:
|
||||
def __init__(self) -> None:
|
||||
self.temp = tempfile.TemporaryDirectory(prefix="codex-mmo-test-")
|
||||
self.root = Path(self.temp.name)
|
||||
self.config = self.root / "config with spaces"
|
||||
self.state = self.root / "state with spaces"
|
||||
self.runtime = self.root / "runtime with spaces"
|
||||
self.workspace = self.root / "workspace with spaces"
|
||||
self.base_codex_home = self.root / "base codex home"
|
||||
self.old_env: dict[str, str | None] = {}
|
||||
|
||||
def __enter__(self) -> RuntimeSandbox:
|
||||
for path in (
|
||||
self.config,
|
||||
self.state,
|
||||
self.runtime,
|
||||
self.workspace,
|
||||
self.base_codex_home,
|
||||
):
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
self.old_env = {
|
||||
key: os.environ.get(key)
|
||||
for key in (
|
||||
"MMO_INSTALL_ROOT",
|
||||
"MMO_CONFIG_ROOT",
|
||||
"MMO_STATE_ROOT",
|
||||
"XDG_RUNTIME_DIR",
|
||||
"MMO_CODEX_BIN",
|
||||
"ZAI_CODING_API_KEY",
|
||||
"OPENCODE_API_KEY",
|
||||
"OPENROUTER_API_KEY",
|
||||
"OPENAI_API_KEY",
|
||||
"FIRECRAWL_API_KEY",
|
||||
"IDA_MCP_TOKEN",
|
||||
"CODEX_HOME",
|
||||
)
|
||||
}
|
||||
os.environ.update(
|
||||
{
|
||||
"MMO_INSTALL_ROOT": str(ROOT),
|
||||
"MMO_CONFIG_ROOT": str(self.config),
|
||||
"MMO_STATE_ROOT": str(self.state),
|
||||
"XDG_RUNTIME_DIR": str(self.runtime),
|
||||
"MMO_CODEX_BIN": str(FAKE_CODEX),
|
||||
"ZAI_CODING_API_KEY": "fake-zai-coding",
|
||||
"OPENCODE_API_KEY": "fake-opencode",
|
||||
"OPENROUTER_API_KEY": "fake-openrouter",
|
||||
"OPENAI_API_KEY": "fake-openai",
|
||||
}
|
||||
)
|
||||
(self.config / "profiles.d").mkdir()
|
||||
(self.config / "catalog.d").mkdir()
|
||||
(self.config / "tool-mcp.d").mkdir()
|
||||
settings = (ROOT / "config" / "settings.toml").read_text(encoding="utf-8")
|
||||
settings = settings.replace(
|
||||
'base_codex_home = "~/.codex"', f"base_codex_home = {self.base_codex_home.as_posix()!r}"
|
||||
)
|
||||
# TOML accepts JSON-style double quoted paths, not Python repr single quotes.
|
||||
settings = settings.replace(
|
||||
f"base_codex_home = '{self.base_codex_home.as_posix()}'",
|
||||
f'base_codex_home = "{self.base_codex_home.as_posix()}"',
|
||||
)
|
||||
settings = settings.replace(
|
||||
'switchyard_bin = "switchyard-server"',
|
||||
f'switchyard_bin = "{FAKE_SWITCHYARD.as_posix()}"',
|
||||
)
|
||||
settings = settings.replace(
|
||||
"gateway_start_timeout_seconds = 15", "gateway_start_timeout_seconds = 5"
|
||||
)
|
||||
settings = settings.replace(
|
||||
"gateway_idle_timeout_seconds = 3600", "gateway_idle_timeout_seconds = 1"
|
||||
)
|
||||
(self.config / "settings.toml").write_text(settings, encoding="utf-8")
|
||||
(self.config / "credentials.env").write_text(
|
||||
"ZAI_CODING_API_KEY=fake-zai-coding\nOPENCODE_API_KEY=fake-opencode\n"
|
||||
"OPENROUTER_API_KEY=fake-openrouter\nOPENAI_API_KEY=fake-openai\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(self.base_codex_home / "auth.json").write_text('{"fake":true}\n', encoding="utf-8")
|
||||
return self
|
||||
|
||||
def __exit__(self, *_exc: object) -> None:
|
||||
with contextlib.suppress(Exception):
|
||||
from mmo_runtime import cancel_session, iter_sessions
|
||||
|
||||
for session in iter_sessions(strict=False):
|
||||
with contextlib.suppress(Exception):
|
||||
cancel_session(str(session["session_id"]))
|
||||
with contextlib.suppress(Exception):
|
||||
from mmo_gateway import list_gateways, stop_gateway
|
||||
|
||||
for gateway in list_gateways():
|
||||
stop_gateway(str(gateway["snapshot_hash"]))
|
||||
for key, value in self.old_env.items():
|
||||
if value is None:
|
||||
os.environ.pop(key, None)
|
||||
else:
|
||||
os.environ[key] = value
|
||||
self.temp.cleanup()
|
||||
|
||||
def init_git(self) -> None:
|
||||
import subprocess
|
||||
|
||||
subprocess.run(["git", "init", "-q", str(self.workspace)], check=True)
|
||||
subprocess.run(
|
||||
["git", "-C", str(self.workspace), "config", "user.email", "test@example.invalid"],
|
||||
check=True,
|
||||
)
|
||||
subprocess.run(
|
||||
["git", "-C", str(self.workspace), "config", "user.name", "MMO Test"], check=True
|
||||
)
|
||||
(self.workspace / "README.md").write_text("fixture\n", encoding="utf-8")
|
||||
subprocess.run(["git", "-C", str(self.workspace), "add", "."], check=True)
|
||||
subprocess.run(["git", "-C", str(self.workspace), "commit", "-qm", "fixture"], check=True)
|
||||
Reference in New Issue
Block a user