Add codex app-server ChatGPT OAuth provider path#265
Conversation
- add codex-app-server runtime provider and stdio JSON-RPC client - integrate Hermes CLI auth/thread/turn flow via app-server - support ChatGPT OAuth login + existing-session detection - persist codex-app-server sessions/messages in SQLite - add stderr logging and optional RPC transcript logging - update launcher and provider/model selection UX - show explicit per-turn override notice for model/cwd/approval/sandbox - add focused tests for auth, turn lifecycle, and failure handling
|
Im a bit confused as to why we want this when this would require the codex-cli being installed, and our current doesn't rely on it at all? |
|
@teknium1 this doesn't require the codex-cli at all. This would spin up the codex app server |
|
What is the app server exactly I guess I'm still confused xD |
|
The app server is Codex's backend for rich clients, not the Codex terminal UI itself. It speaks JSON-RPC over stdio by default, and it handles things like auth, conversation history, approvals, and streamed agent events. The VS Code extension uses this same surface. In this PR, Hermes becomes a client of that backend. Hermes launches One important clarification, though: this path does require the local |
|
Closing this — Hermes already has a working Codex OAuth path (the
The existing Appreciate the thorough work though — the PR is well-structured. |
Phase 2 Feature 3 backend ST1. Purelymail outbound via aiosmtplib SMTP. - kora_cli/clients/purelymail_types.py: Attachment dataclass + SendResult Pydantic. - kora_cli/clients/purelymail_client.py (595 LOC): PurelymailClient + send_email_internal + sanitize/parse helpers. - tests/kora_cli/clients/test_purelymail_client.py: 40 tests. - pyproject.toml: aiosmtplib==4.0.1 runtime dep (NOT under extra — same lesson as task NousResearch#265). Key contracts pinned by tests: - Fail-CLOSED at __init__ (missing/empty/whitespace username or password). - Unset KORA_EMAIL_KORA_ALLOWED_FROM_DOMAINS = operator-config error (NOT silent allow-all). - Per-attachment 10 MiB / total batch 25 MiB caps. - Retry once on SMTP 421/450/451/452 transient + connection-tier errors; no retry on 5xx permanent / auth error. - Per-call 30s timeout. - Message-ID generated locally via email.utils.make_msgid. - Body NEVER in JSONL log (subject + recipients only). - Password absent from error/repr/log after every diverse failure mode (auth-fail / 5xx-with-echo / connection / disconnect / 421-transient). 40/40 tests pass, 270/270 cross-bucket regression.
…tigation (#125) Two-part cleanup. Part A (tsc drift): HeartbeatPanel.tsx + DashboardPage.tsx now handle all 4 fields KR-FEAT-HEARTBEAT ST2 (#118) added: unknown status arm (muted probe-pending pill + CircleDashed icon), nullable last_check_at (never checked — matching #117 convention), error field rendered as destructive <pre> in expanded view (plain text, no dangerouslySetInnerHTML), cache_warming Probes warming up… banner + dashboard headline-tone suppression. tsc -b clean. Part B (mcp_clients tests): investigation only, STOPPED per spec rule. Root cause is NOT stale assertions — all 13 failures + 5 errors collapse on ModuleNotFoundError: No module named slowapi from the unconditional import chain web_server → listeners/__init__ → listeners/webhooks → slowapi. Verified by installing --extra web: 19/19 mcp_clients tests pass. This is task NousResearch#265 (slowapi placement). Recommended 1-line fix: move slowapi to runtime deps. Will dispatch as standalone KR-SLOWAPI-DEP-FIX bucket. 3 files, +267/-14 panel + dashboard + 11 new source-pin tests. 260/260 admin-panel tests pass across 22 suites (with --extra web installed). tsc -b + vite build both clean.
Closes BOTH task NousResearch#265 (slowapi placement) AND task NousResearch#269 (mcp_clients test failures — confirmed downstream of same import-chain issue per CC#2 investigation in PR #125). - pyproject.toml: slowapi==0.1.9 moves from [web] optional-deps to runtime deps (next to aiosmtplib pin that set the precedent in PR #124). - uv.lock regenerated. - Exact-equals pin per the security policy in the dependencies-block header (2026-05-12 Mini Shai-Hulud response). Base-install verification (uv sync --frozen --extra dev, NO --extra web): mcp_clients 19/19 pass (was 13 fail + 5 err); full admin-panel regression 271/271 across 23 suites.
Background
codex app-serveris Codex’s stateful JSON-RPC integration surface for rich clients. Instead of calling model endpoints directly, a client talks to app-server, and app-server manages auth/account state, thread/turn lifecycle, streaming item events, approvals, and Codex config layering (~/.codex/config.toml+ project.codex/config.tomlin trusted repos).Hermes historically ran through direct OpenAI-compatible client calls. This PR adds an explicit
codex-app-serverprovider path so Hermes can operate as an app-server client.Why this change
--provider codex-app-server)What changed
codex-app-serverhermes_cli/codex_app_server.py)~/.hermes/logs/codex-app-server.log~/.hermes/logs/codex-app-server-rpc.log(enable withHERMES_CODEX_APP_SERVER_RPC_LOG=1)hermes modelsupport for selectingcodex-app-serverhermes setupprovider flow forcodex-app-server(including model selection and keep-current detection)stdio://...)item/started+item/completedevents into Hermes progress modes (off|new|all|verbose) in CLI and gatewayagent.reasoning_effortto app-serverturn/start.effortxhigh -> high,minimal -> low,high|medium|low -> unchanged,none -> omithermes chatnow uses--modelonly (removed-malias) to avoidmodelvsmax_turnsambiguityCompatibility note
Hermes currently sets these fields explicitly on app-server
thread/start/turn/startrequests:modelcwdapprovalPolicy=neversandboxPolicy=workspaceWrite+networkEnabledIf those are also configured in
~/.codex/config.toml, Hermes request-level values win for those fields. Other Codex behavior still follows app-server config layering.For reasoning effort:
agent.reasoning_effortis set in Hermes config, Hermes sendsefforton turn/startnone, Hermes omitseffort, allowing Codex defaults/config layering to applyTests
pytest -q tests/test_codex_app_server_cli.pypytest -q tests/test_codex_app_server_cli.py tests/test_cli_provider_resolution.py tests/test_runtime_provider_resolution.py tests/test_auth_codex_provider.py tests/test_codex_models.py tests/test_codex_execution_paths.pypytest -q tests/test_codex_models.py tests/test_runtime_provider_resolution.pypytest -q tests/test_runtime_provider_resolution.py tests/test_codex_app_server_cli.py tests/gateway/test_channel_directory.pypytest -q tests/test_codex_app_server_cli.py tests/test_runtime_provider_resolution.py tests/test_cli_provider_resolution.py tests/gateway/test_channel_directory.pyLatest targeted run in this branch: 30 passed.