Delete unread model adapter status families

This commit is contained in:
Meta Vens 2026-08-24 05:03:45 +02:00
commit 0091e0e122
8 changed files with 6 additions and 267 deletions

View file

@ -47,12 +47,10 @@ use cultcache_rs::CacheBackingStore;
use cultcache_rs::CultCache;
use cultcache_rs::CultCacheEnvelope;
use cultcache_rs::DatabaseEntry;
use epiphany_model_adapter::EpiphanyModelAdapterStatus;
use epiphany_model_adapter::EpiphanyModelReceipt;
use epiphany_model_adapter::EpiphanyModelRequest;
use epiphany_model_adapter::EpiphanyModelStreamEvent;
use epiphany_model_adapter::EpiphanyModelStreamPayload;
use epiphany_openai_adapter::EpiphanyOpenAiAdapterStatus;
use epiphany_openai_adapter::EpiphanyOpenAiModelReceipt;
use epiphany_openai_adapter::EpiphanyOpenAiModelRequest;
use epiphany_openai_adapter::EpiphanyOpenAiStreamEvent;
@ -88,7 +86,7 @@ pub const COORDINATOR_RUN_RECEIPT_TYPE: &str = "epiphany.coordinator_run_receipt
pub const RUNTIME_IDENTITY_KEY: &str = "self";
pub const RUNTIME_SWARM_BINDING_KEY: &str = "runtime-swarm-binding";
pub const RUNTIME_SWARM_BINDING_SCHEMA_VERSION: &str = "epiphany.runtime.swarm_binding.v1";
pub const RUNTIME_SPINE_SCHEMA_VERSION: &str = "epiphany.runtime_spine.v22";
pub const RUNTIME_SPINE_SCHEMA_VERSION: &str = "epiphany.runtime_spine.v23";
pub const EPIPHANY_RUNTIME_ROOT_SESSION_ID: &str = "epiphany-main";
pub const RUNTIME_MODEL_EXECUTION_BINDING_SCHEMA_VERSION: &str =
"epiphany.runtime.model_execution_binding.v0";
@ -863,11 +861,9 @@ fn runtime_spine_schema_cache() -> Result<CultCache> {
cache.register_entry_type::<HandsCommitReceipt>()?;
cache.register_entry_type::<SoulVerdictReceipt>()?;
cache.register_entry_type::<ContinuityRecoveryReceipt>()?;
cache.register_entry_type::<EpiphanyOpenAiAdapterStatus>()?;
cache.register_entry_type::<EpiphanyOpenAiModelRequest>()?;
cache.register_entry_type::<EpiphanyOpenAiStreamEvent>()?;
cache.register_entry_type::<EpiphanyOpenAiModelReceipt>()?;
cache.register_entry_type::<EpiphanyModelAdapterStatus>()?;
cache.register_entry_type::<EpiphanyModelRequest>()?;
cache.register_entry_type::<EpiphanyModelStreamEvent>()?;
cache.register_entry_type::<EpiphanyModelReceipt>()?;

View file

@ -5,28 +5,6 @@ use serde::Serialize;
pub const MODEL_ADAPTER_REQUEST_SCHEMA_ID: &str = "epiphany.model_request.v0";
pub const MODEL_ADAPTER_EVENT_SCHEMA_ID: &str = "epiphany.model_stream_event.v0";
pub const MODEL_ADAPTER_RECEIPT_SCHEMA_ID: &str = "epiphany.model_receipt.v0";
pub const MODEL_ADAPTER_STATUS_SCHEMA_ID: &str = "epiphany.model_adapter_status.v0";
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.model_adapter_status.v0",
schema = "EpiphanyModelAdapterStatus"
)]
pub struct EpiphanyModelAdapterStatus {
#[cultcache(key = 0)]
pub schema_id: String,
#[cultcache(key = 1)]
pub adapter_id: String,
#[cultcache(key = 2)]
pub provider: String,
#[cultcache(key = 3, default)]
pub default_model: Option<String>,
#[cultcache(key = 4)]
pub streaming_supported: bool,
#[cultcache(key = 5)]
pub provider_transport_attached: bool,
}
#[derive(Debug, Clone, PartialEq, DatabaseEntry)]
#[cultcache(type = "epiphany.model_request.v0", schema = "EpiphanyModelRequest")]
pub struct EpiphanyModelRequest {

View file

@ -6,46 +6,12 @@ use serde::Serialize;
pub const OPENAI_ADAPTER_REQUEST_SCHEMA_ID: &str = "epiphany.openai_model_request.v1";
pub const OPENAI_ADAPTER_EVENT_SCHEMA_ID: &str = "epiphany.openai_model_stream_event.v0";
pub const OPENAI_ADAPTER_RECEIPT_SCHEMA_ID: &str = "epiphany.openai_model_receipt.v0";
pub const OPENAI_ADAPTER_STATUS_SCHEMA_ID: &str = "epiphany.openai_adapter_status.v0";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum EpiphanyOpenAiAuthMode {
ChatGptSubscription,
ApiKey,
ExternalBearer,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum EpiphanyOpenAiWireDialect {
Responses,
ChatCompletionsTerminalTool,
}
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
#[cultcache(
type = "epiphany.openai_adapter_status.v0",
schema = "EpiphanyOpenAiAdapterStatus"
)]
pub struct EpiphanyOpenAiAdapterStatus {
#[cultcache(key = 0)]
pub schema_id: String,
#[cultcache(key = 1)]
pub adapter_id: String,
#[cultcache(key = 2)]
pub auth_mode: EpiphanyOpenAiAuthMode,
#[cultcache(key = 3, default)]
pub account_id: Option<String>,
#[cultcache(key = 4, default)]
pub plan_type: Option<String>,
#[cultcache(key = 5, default)]
pub default_model: Option<String>,
#[cultcache(key = 6)]
pub supports_websockets: bool,
#[cultcache(key = 7)]
pub codex_transport_attached: bool,
}
#[derive(Debug, Clone, PartialEq, DatabaseEntry)]
#[cultcache(
type = "epiphany.openai_model_request.v1",

View file

@ -9,18 +9,14 @@ use codex_client::Request;
use codex_client::ReqwestTransport;
use codex_client::TransportError;
use codex_client::sse_stream;
use epiphany_openai_adapter::EpiphanyOpenAiAdapterStatus;
use epiphany_openai_adapter::EpiphanyOpenAiAuthMode;
use epiphany_openai_adapter::EpiphanyOpenAiInputItem;
use epiphany_openai_adapter::EpiphanyOpenAiModelReceipt;
use epiphany_openai_adapter::EpiphanyOpenAiModelRequest;
use epiphany_openai_adapter::EpiphanyOpenAiStreamEvent;
use epiphany_openai_adapter::EpiphanyOpenAiStreamPayload;
use epiphany_openai_adapter::EpiphanyOpenAiWireDialect;
use epiphany_openai_adapter::OPENAI_ADAPTER_STATUS_SCHEMA_ID;
use codex_login::AuthCredentialsStoreMode;
use codex_login::AuthManager;
use codex_login::AuthMode;
use codex_login::CodexAuth;
use codex_login::default_client::build_reqwest_client;
use serde::Deserialize;
@ -37,8 +33,6 @@ const OPENROUTER_API_BASE_URL: &str = "https://openrouter.ai/api/v1";
const RESPONSES_STREAM_IDLE_TIMEOUT: Duration = Duration::from_secs(45);
const RESPONSES_CALL_ID_MAX_BYTES: usize = 64;
pub const CODEX_SPINE_ADAPTER_ID: &str = "codex-openai-subscription-spine";
pub const OPENROUTER_SPINE_ADAPTER_ID: &str = "openrouter-chat-completions-spine";
pub const OPENROUTER_TERMINAL_TOOL_NAME: &str = "epiphany_submit_typed_result";
pub fn default_codex_home() -> Result<std::path::PathBuf> {
@ -60,47 +54,6 @@ pub fn auth_manager(codex_home: std::path::PathBuf) -> Arc<AuthManager> {
)
}
pub async fn status_from_auth_manager(
auth_manager: &AuthManager,
default_model: Option<String>,
supports_websockets: bool,
) -> EpiphanyOpenAiAdapterStatus {
let auth = auth_manager.auth().await;
let auth_mode = auth_mode_from_manager(auth_manager, auth.as_ref());
let account_id = auth.as_ref().and_then(CodexAuth::get_account_id);
let plan_type = auth
.as_ref()
.and_then(CodexAuth::account_plan_type)
.map(|plan| format!("{plan:?}"));
EpiphanyOpenAiAdapterStatus {
schema_id: OPENAI_ADAPTER_STATUS_SCHEMA_ID.to_string(),
adapter_id: CODEX_SPINE_ADAPTER_ID.to_string(),
auth_mode,
account_id,
plan_type,
default_model,
supports_websockets,
codex_transport_attached: true,
}
}
pub fn status_from_static_api_key(
adapter_id: &str,
default_model: Option<String>,
) -> EpiphanyOpenAiAdapterStatus {
EpiphanyOpenAiAdapterStatus {
schema_id: OPENAI_ADAPTER_STATUS_SCHEMA_ID.to_string(),
adapter_id: adapter_id.to_string(),
auth_mode: EpiphanyOpenAiAuthMode::ApiKey,
account_id: None,
plan_type: None,
default_model,
supports_websockets: false,
codex_transport_attached: false,
}
}
pub struct EpiphanyCodexOpenAiTransport {
auth_manager: Arc<AuthManager>,
base_url: Option<String>,
@ -1457,33 +1410,6 @@ fn transport_error_to_anyhow(err: TransportError) -> anyhow::Error {
anyhow::anyhow!("failed to open provider transport: {err}")
}
fn auth_mode_from_manager(
auth_manager: &AuthManager,
auth: Option<&CodexAuth>,
) -> EpiphanyOpenAiAuthMode {
match auth_manager.auth_mode() {
Some(AuthMode::ApiKey) => EpiphanyOpenAiAuthMode::ApiKey,
Some(AuthMode::Chatgpt) | Some(AuthMode::ChatgptAuthTokens) => {
EpiphanyOpenAiAuthMode::ChatGptSubscription
}
Some(AuthMode::AgentIdentity) => EpiphanyOpenAiAuthMode::ExternalBearer,
None => auth_mode_from_codex_auth(auth),
}
}
fn auth_mode_from_codex_auth(auth: Option<&CodexAuth>) -> EpiphanyOpenAiAuthMode {
let Some(auth) = auth else {
return EpiphanyOpenAiAuthMode::Unknown;
};
if auth.is_api_key_auth() {
EpiphanyOpenAiAuthMode::ApiKey
} else if auth.is_chatgpt_auth() {
EpiphanyOpenAiAuthMode::ChatGptSubscription
} else {
EpiphanyOpenAiAuthMode::ExternalBearer
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -1504,20 +1430,6 @@ mod tests {
request
}
#[test]
fn static_openrouter_status_does_not_claim_codex_transport() {
let status = status_from_static_api_key(
OPENROUTER_SPINE_ADAPTER_ID,
Some("stealth/ox-alpha".to_string()),
);
assert_eq!(status.adapter_id, OPENROUTER_SPINE_ADAPTER_ID);
assert_eq!(status.auth_mode, EpiphanyOpenAiAuthMode::ApiKey);
assert_eq!(status.default_model.as_deref(), Some("stealth/ox-alpha"));
assert!(!status.supports_websockets);
assert!(!status.codex_transport_attached);
}
#[test]
fn openrouter_whole_request_timeout_is_explicit() -> Result<()> {
let bounded = EpiphanyOpenRouterTransport::new("test-key", Some(Duration::from_secs(90)))?;

View file

@ -31,17 +31,13 @@ use epiphany_model_adapter::EpiphanyModelRequest;
use epiphany_model_adapter::EpiphanyModelStreamEvent;
use epiphany_model_adapter::EpiphanyModelStreamPayload;
use epiphany_model_adapter::EpiphanyModelToolDefinition;
use epiphany_openai_adapter::EpiphanyOpenAiAdapterStatus;
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::EpiphanyOpenRouterTransport;
use epiphany_openai_codex_spine::OPENROUTER_SPINE_ADAPTER_ID;
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 epiphany_openai_codex_spine::status_from_static_api_key;
use epiphany_tool_adapter::EPIPHANY_TOOL_RUNTIME_ADAPTER_ID;
use epiphany_tool_adapter::EpiphanyToolInvocationIntent;
use epiphany_tool_adapter::EpiphanyToolInvocationReceipt;
@ -78,10 +74,6 @@ impl EpiphanyProviderProfile {
)),
}
}
fn streaming_supported(self) -> bool {
matches!(self, Self::OpenAiCodex)
}
}
pub fn worker_model_session_id(worker_job_id: &str) -> String {
@ -171,41 +163,23 @@ async fn run_openai_model_turn_bound(
&model_request,
&now(),
)?;
let (status, events) = match profile {
let events = match profile {
EpiphanyProviderProfile::OpenAiCodex => {
let auth_manager = auth_manager(options.codex_home.clone());
let status =
status_from_auth_manager(&auth_manager, options.default_model.clone(), true).await;
let transport = EpiphanyCodexOpenAiTransport::openai(auth_manager);
let events =
collect_transport_events(transport.collect_model_events(request.clone()), &request)
.await;
(status, events)
collect_transport_events(transport.collect_model_events(request.clone()), &request)
.await
}
EpiphanyProviderProfile::OpenRouter => {
let credential = read_static_provider_credential(
options.provider_credential_path.as_deref(),
OPENROUTER_MODEL_PROVIDER,
)?;
let status = status_from_static_api_key(
OPENROUTER_SPINE_ADAPTER_ID,
options.default_model.clone(),
);
let transport = EpiphanyOpenRouterTransport::new(credential, options.request_timeout)?;
let events =
collect_transport_events(transport.collect_model_events(request.clone()), &request)
.await;
(status, events)
collect_transport_events(transport.collect_model_events(request.clone()), &request)
.await
}
};
store_openai_status(&options.store_path, &status)?;
store_model_status(
&options.store_path,
&status,
&provider,
profile.streaming_supported(),
true,
)?;
record_openai_events(&options.store_path, &options, &request, &provider, &events)
}
@ -884,37 +858,6 @@ pub fn ensure_openai_runtime_ready(options: &EpiphanyOpenAiRuntimeOptions) -> Re
Ok(())
}
pub fn store_openai_status(
store_path: impl AsRef<Path>,
status: &EpiphanyOpenAiAdapterStatus,
) -> Result<()> {
let mut cache = runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
cache.put(status.adapter_id.clone(), status)?;
Ok(())
}
pub fn store_model_status(
store_path: impl AsRef<Path>,
status: &EpiphanyOpenAiAdapterStatus,
provider: &str,
streaming_supported: bool,
provider_transport_attached: bool,
) -> Result<()> {
let mut cache = runtime_spine_cache(store_path)?;
cache.pull_all_backing_stores()?;
let status = epiphany_model_adapter::EpiphanyModelAdapterStatus {
schema_id: epiphany_model_adapter::MODEL_ADAPTER_STATUS_SCHEMA_ID.to_string(),
adapter_id: status.adapter_id.clone(),
provider: provider.to_string(),
default_model: status.default_model.clone(),
streaming_supported,
provider_transport_attached,
};
cache.put(status.adapter_id.clone(), &status)?;
Ok(())
}
pub fn store_model_request(
store_path: impl AsRef<Path>,
request: &EpiphanyModelRequest,

View file

@ -1,16 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.model-adapter-status.schema.json",
"title": "Epiphany Model Adapter Status",
"type": "object",
"required": ["schema_id", "adapter_id", "provider", "streaming_supported", "provider_transport_attached"],
"properties": {
"schema_id": { "const": "epiphany.model_adapter_status.v0" },
"adapter_id": { "type": "string" },
"provider": { "type": "string" },
"default_model": { "type": ["string", "null"] },
"streaming_supported": { "type": "boolean" },
"provider_transport_attached": { "type": "boolean" }
},
"additionalProperties": false
}

View file

@ -1,18 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://gamecult.dev/epiphany/cultnet/epiphany.openai-adapter-status.schema.json",
"title": "Epiphany OpenAI Adapter Status",
"type": "object",
"required": ["schema_id", "adapter_id", "auth_mode", "supports_websockets", "codex_transport_attached"],
"properties": {
"schema_id": { "const": "epiphany.openai_adapter_status.v0" },
"adapter_id": { "type": "string" },
"auth_mode": { "enum": ["ChatGptSubscription", "ApiKey", "ExternalBearer", "Unknown"] },
"account_id": { "type": ["string", "null"] },
"plan_type": { "type": ["string", "null"] },
"default_model": { "type": ["string", "null"] },
"supports_websockets": { "type": "boolean" },
"codex_transport_attached": { "type": "boolean" }
},
"additionalProperties": false
}

View file

@ -100,17 +100,6 @@
"title": "Epiphany Coordinator Run Receipt",
"path": "epiphany.coordinator-run-receipt.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.model-adapter-status.schema.json",
"kind": "document_payload",
"wireContracts": [
"cultnet.schema.v0"
],
"schemaVersion": "epiphany.model_adapter_status.v0",
"documentType": "epiphany.model_adapter_status.v0",
"title": "Epiphany Model Adapter Status",
"path": "epiphany.model-adapter-status.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.model-request.schema.json",
"kind": "document_payload",
@ -166,17 +155,6 @@
"title": "Epiphany Tool Invocation Receipt",
"path": "epiphany.tool-invocation-receipt.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.openai-adapter-status.schema.json",
"kind": "document_payload",
"wireContracts": [
"cultnet.schema.v0"
],
"schemaVersion": "epiphany.openai_adapter_status.v0",
"documentType": "epiphany.openai_adapter_status.v0",
"title": "Epiphany OpenAI Adapter Status",
"path": "epiphany.openai-adapter-status.schema.json"
},
{
"schemaId": "https://gamecult.dev/epiphany/cultnet/epiphany.openai-model-request.schema.json",
"kind": "document_payload",