Hide Codex login behind OpenAI spine

This commit is contained in:
Meta Vens 2026-05-13 10:36:29 +01:00
commit 59f0782400
7 changed files with 31 additions and 46 deletions

View file

@ -1,17 +1,16 @@
use std::env;
use std::fs;
use std::path::PathBuf;
use std::sync::Arc;
use anyhow::Context;
use anyhow::Result;
use anyhow::anyhow;
use codex_login::AuthCredentialsStoreMode;
use codex_login::AuthManager;
use codex_login::CodexAuth;
use epiphany_openai_adapter::EpiphanyOpenAiInputItem;
use epiphany_openai_adapter::EpiphanyOpenAiModelRequest;
use epiphany_openai_codex_spine::EpiphanyCodexOpenAiTransport;
use epiphany_openai_codex_spine::auth_manager;
use epiphany_openai_codex_spine::default_codex_home;
use epiphany_openai_codex_spine::responses_request_from_epiphany;
use epiphany_openai_codex_spine::status_from_auth_manager;
use epiphany_openai_codex_spine::status_from_codex_auth;
@ -129,25 +128,6 @@ fn next_value(iter: &mut impl Iterator<Item = String>, name: &str) -> Result<Str
.ok_or_else(|| anyhow!("{name} requires a value"))
}
fn default_codex_home() -> Result<PathBuf> {
if let Ok(path) = env::var("CODEX_HOME") {
return Ok(PathBuf::from(path));
}
let home = env::var("USERPROFILE")
.or_else(|_| env::var("HOME"))
.context("CODEX_HOME is unset and no home directory environment variable exists")?;
Ok(PathBuf::from(home).join(".codex"))
}
fn auth_manager(codex_home: PathBuf) -> Arc<AuthManager> {
AuthManager::shared(
codex_home,
/*enable_codex_api_key_env*/ true,
AuthCredentialsStoreMode::File,
/*chatgpt_base_url*/ None,
)
}
fn print_json<T: serde::Serialize>(value: &T) -> Result<()> {
println!("{}", serde_json::to_string_pretty(value)?);
Ok(())

View file

@ -10,6 +10,7 @@ use codex_api::ResponseEvent;
use codex_api::ResponsesApiRequest;
use codex_api::ResponsesClient;
use codex_api::ResponsesOptions;
use codex_login::AuthCredentialsStoreMode;
use codex_login::AuthManager;
use codex_login::AuthMode;
use codex_login::CodexAuth;
@ -34,6 +35,25 @@ use futures::StreamExt;
pub const CODEX_SPINE_ADAPTER_ID: &str = "codex-openai-subscription-spine";
pub fn default_codex_home() -> Result<std::path::PathBuf> {
if let Ok(path) = std::env::var("CODEX_HOME") {
return Ok(std::path::PathBuf::from(path));
}
let home = std::env::var("USERPROFILE")
.or_else(|_| std::env::var("HOME"))
.context("CODEX_HOME is unset and no home directory environment variable exists")?;
Ok(std::path::PathBuf::from(home).join(".codex"))
}
pub fn auth_manager(codex_home: std::path::PathBuf) -> Arc<AuthManager> {
AuthManager::shared(
codex_home,
/*enable_codex_api_key_env*/ true,
AuthCredentialsStoreMode::File,
/*chatgpt_base_url*/ None,
)
}
pub async fn status_from_auth_manager(
auth_manager: &AuthManager,
default_model: Option<String>,

View file

@ -12,7 +12,6 @@ path = "src/lib.rs"
[dependencies]
anyhow = "1"
chrono = "0.4.44"
codex-login = { path = "../vendor/codex/codex-rs/login" }
epiphany-core = { path = "../epiphany-core" }
epiphany-openai-adapter = { path = "../epiphany-openai-adapter" }
epiphany-openai-codex-spine = { path = "../epiphany-openai-codex-spine" }

View file

@ -1,13 +1,10 @@
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use anyhow::Context;
use anyhow::Result;
use anyhow::anyhow;
use chrono::SecondsFormat;
use codex_login::AuthCredentialsStoreMode;
use codex_login::AuthManager;
use epiphany_core::EpiphanyRuntimeReorientWorkerResult;
use epiphany_core::EpiphanyRuntimeRoleWorkerResult;
use epiphany_core::EpiphanyRuntimeWorkerLaunchRequest;
@ -32,6 +29,8 @@ use epiphany_openai_adapter::EpiphanyOpenAiModelRequest;
use epiphany_openai_adapter::EpiphanyOpenAiStreamEvent;
use epiphany_openai_adapter::EpiphanyOpenAiStreamPayload;
use epiphany_openai_codex_spine::EpiphanyCodexOpenAiTransport;
use epiphany_openai_codex_spine::auth_manager;
pub use epiphany_openai_codex_spine::default_codex_home;
use epiphany_openai_codex_spine::status_from_auth_manager;
use serde_json::Value;
@ -458,16 +457,6 @@ pub fn assistant_text_from_openai_events(
Ok(text)
}
pub fn default_codex_home() -> Result<PathBuf> {
if let Ok(path) = std::env::var("CODEX_HOME") {
return Ok(PathBuf::from(path));
}
let home = std::env::var("USERPROFILE")
.or_else(|_| std::env::var("HOME"))
.context("CODEX_HOME is unset and no home directory environment variable exists")?;
Ok(PathBuf::from(home).join(".codex"))
}
pub fn default_options(
store_path: PathBuf,
codex_home: PathBuf,
@ -485,15 +474,6 @@ pub fn default_options(
}
}
pub fn auth_manager(codex_home: PathBuf) -> Arc<AuthManager> {
AuthManager::shared(
codex_home,
/*enable_codex_api_key_env*/ true,
AuthCredentialsStoreMode::File,
/*chatgpt_base_url*/ None,
)
}
pub fn openai_event_key(request_id: &str, sequence: u64) -> String {
format!("{request_id}:{sequence:08}")
}

View file

@ -579,6 +579,12 @@ native runtime/CultNet model calls through this spine and then shrinking the
surviving Codex dependency surface to auth, provider/model routing, and the
smallest OpenAI Responses call needed for subscription compatibility.
The native runtime no longer imports `codex-login` directly. The Codex spine now
exports the `default_codex_home` and `auth_manager` helpers, so
`epiphany-openai-runtime` reaches Codex credentials only through
`epiphany-openai-codex-spine`. Keep that boundary: if native runtime code needs
credential details, the spine owns the adapter surface.
That native route has now started. `epiphany-openai-adapter` documents are
CultCache `DatabaseEntry` types, `epiphany-core::runtime_spine_cache` registers
OpenAI adapter status/request/stream-event/receipt records, and the

Binary file not shown.

File diff suppressed because one or more lines are too long