Collapse model adapter package boundary
This commit is contained in:
parent
b83c041670
commit
a721b76372
14 changed files with 224 additions and 251 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -543,7 +543,6 @@ dependencies = [
|
|||
"cultnet-rs",
|
||||
"ed25519-dalek",
|
||||
"epiphany-model-adapter",
|
||||
"epiphany-openai-adapter",
|
||||
"epiphany-release-construction",
|
||||
"epiphany-tool-adapter",
|
||||
"ghostlight-persona-projection",
|
||||
|
|
@ -562,19 +561,10 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "epiphany-model-adapter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cultcache-rs",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "epiphany-openai-adapter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"codex-connector",
|
||||
"cultcache-rs",
|
||||
"epiphany-model-adapter",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
|
|
@ -589,7 +579,6 @@ dependencies = [
|
|||
"cultcache-rs",
|
||||
"epiphany-core",
|
||||
"epiphany-model-adapter",
|
||||
"epiphany-openai-adapter",
|
||||
"epiphany-tool-adapter",
|
||||
"rmp-serde",
|
||||
"serde",
|
||||
|
|
@ -612,7 +601,6 @@ dependencies = [
|
|||
"cultnet-rs",
|
||||
"epiphany-core",
|
||||
"epiphany-model-adapter",
|
||||
"epiphany-openai-adapter",
|
||||
"epiphany-openai-runtime",
|
||||
"epiphany-tool-adapter",
|
||||
"epiphany-tool-mcp-runtime",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
members = [
|
||||
"epiphany-core",
|
||||
"epiphany-model-adapter",
|
||||
"epiphany-openai-adapter",
|
||||
"epiphany-openai-runtime",
|
||||
"epiphany-release-construction",
|
||||
"epiphany-tool-adapter",
|
||||
|
|
@ -27,7 +26,6 @@ cultcache-rs = { path = "vendor/cultcache-rs" }
|
|||
cultnet-rs = { path = "vendor/cultnet-rs" }
|
||||
epiphany-core = { path = "epiphany-core" }
|
||||
epiphany-model-adapter = { path = "epiphany-model-adapter" }
|
||||
epiphany-openai-adapter = { path = "epiphany-openai-adapter" }
|
||||
epiphany-openai-runtime = { path = "epiphany-openai-runtime", optional = true }
|
||||
codex-connector = { git = "https://github.com/GameCult/CodexConnector", rev = "6dc80f6d266db4d82566d2434adcc55a48e8ecad", default-features = false, features = ["client"], optional = true }
|
||||
epiphany-tool-adapter = { path = "epiphany-tool-adapter" }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ ctrlc = { version = "3.5.1", features = ["termination"] }
|
|||
cultcache-rs = { path = "../vendor/cultcache-rs" }
|
||||
cultmesh-rs = { path = "../vendor/cultmesh-rs" }
|
||||
cultnet-rs = { path = "../vendor/cultnet-rs" }
|
||||
epiphany-openai-adapter = { path = "../epiphany-openai-adapter" }
|
||||
epiphany-release-construction = { path = "../epiphany-release-construction" }
|
||||
epiphany-model-adapter = { path = "../epiphany-model-adapter" }
|
||||
epiphany-tool-adapter = { path = "../epiphany-tool-adapter" }
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ use crate::{
|
|||
};
|
||||
use anyhow::{Result, anyhow};
|
||||
use cultcache_rs::{CacheBackingStore, CultCache, CultCacheEnvelope, DatabaseEntry};
|
||||
use epiphany_model_adapter::EpiphanyModelRequest;
|
||||
use epiphany_openai_adapter::EpiphanyProviderRequest;
|
||||
#[cfg(test)]
|
||||
use epiphany_openai_adapter::EpiphanyProviderRequestPayload;
|
||||
use epiphany_model_adapter::EpiphanyProviderRequestPayload;
|
||||
use epiphany_model_adapter::{EpiphanyModelRequest, EpiphanyProviderRequest};
|
||||
use epiphany_tool_adapter::{
|
||||
EpiphanyToolInvocationIntent, EpiphanyToolInvocationReceipt, receipt_output_for_model,
|
||||
tool_invocation_intent_key, tool_invocation_receipt_key,
|
||||
|
|
@ -371,7 +370,7 @@ impl EpiphanyDecisionContext {
|
|||
tool_observations: Vec<EpiphanyDecisionToolObservation>,
|
||||
) -> Result<Self> {
|
||||
basis.validate()?;
|
||||
let provider_request = epiphany_openai_adapter::request_from_native(&native_request)?;
|
||||
let provider_request = epiphany_model_adapter::request_from_native(&native_request)?;
|
||||
validate_request_pair(basis, &native_request, &provider_request)?;
|
||||
validate_tool_observations(&native_request, &tool_observations)?;
|
||||
let mut context = Self {
|
||||
|
|
@ -1699,7 +1698,7 @@ fn validate_request_pair(
|
|||
if native.reasoning_basis_id.as_deref() != Some(basis.basis_id.as_str()) {
|
||||
return Err(anyhow!("model request does not bind its reasoning basis"));
|
||||
}
|
||||
if provider != &epiphany_openai_adapter::request_from_native(native)? {
|
||||
if provider != &epiphany_model_adapter::request_from_native(native)? {
|
||||
return Err(anyhow!("native and provider terminal requests diverge"));
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -1995,7 +1994,7 @@ mod tests {
|
|||
native.input.push(EpiphanyModelInputItem::UserText {
|
||||
text: "projection".into(),
|
||||
});
|
||||
let provider = epiphany_openai_adapter::request_from_native(&native).unwrap();
|
||||
let provider = epiphany_model_adapter::request_from_native(&native).unwrap();
|
||||
(native, provider)
|
||||
}
|
||||
|
||||
|
|
@ -2072,7 +2071,7 @@ mod tests {
|
|||
)?;
|
||||
assert_eq!(
|
||||
tool_context.provider_request()?,
|
||||
epiphany_openai_adapter::request_from_native(&native_with_substituted_tools)?,
|
||||
epiphany_model_adapter::request_from_native(&native_with_substituted_tools)?,
|
||||
"provider request must be derived from the complete native request"
|
||||
);
|
||||
|
||||
|
|
@ -2172,7 +2171,7 @@ mod tests {
|
|||
));
|
||||
assert_eq!(
|
||||
provider,
|
||||
epiphany_openai_adapter::request_from_native(&native)?
|
||||
epiphany_model_adapter::request_from_native(&native)?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ use epiphany_model_adapter::EpiphanyModelReceipt;
|
|||
use epiphany_model_adapter::EpiphanyModelRequest;
|
||||
use epiphany_model_adapter::EpiphanyModelStreamEvent;
|
||||
use epiphany_model_adapter::EpiphanyModelStreamPayload;
|
||||
use epiphany_openai_adapter::EpiphanyProviderRequest;
|
||||
use epiphany_model_adapter::EpiphanyProviderRequest;
|
||||
use epiphany_tool_adapter::EpiphanyToolInvocationIntent;
|
||||
use epiphany_tool_adapter::EpiphanyToolInvocationReceipt;
|
||||
use epiphany_tool_adapter::TOOL_ADAPTER_INVOCATION_INTENT_SCHEMA_ID;
|
||||
|
|
@ -1078,7 +1078,7 @@ pub fn open_runtime_model_execution(
|
|||
validate_non_empty(&job_options.job_id, "model execution job id")?;
|
||||
validate_non_empty(&model_request.request_id, "model execution request id")?;
|
||||
validate_non_empty(&model_request.provider, "model execution provider")?;
|
||||
let provider_request = epiphany_openai_adapter::request_from_native(model_request)?;
|
||||
let provider_request = epiphany_model_adapter::request_from_native(model_request)?;
|
||||
|
||||
let store_path = store_path.as_ref();
|
||||
let mut cache = runtime_spine_cache(store_path)?;
|
||||
|
|
@ -1399,7 +1399,7 @@ pub(crate) fn validate_runtime_model_execution_binding(
|
|||
.get::<EpiphanyRuntimeJob>(&binding.job_id)?
|
||||
.ok_or_else(|| anyhow!("model execution binding {request_id:?} lost its job"))?;
|
||||
if binding.request_id != request_id
|
||||
|| provider != epiphany_openai_adapter::request_from_native(&native)?
|
||||
|| provider != epiphany_model_adapter::request_from_native(&native)?
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"model execution binding {request_id:?} is not one exact request family"
|
||||
|
|
@ -1737,7 +1737,7 @@ fn archive_completed_model_session(
|
|||
.get::<EpiphanyProviderRequest>(request_id)?
|
||||
.ok_or_else(|| anyhow!("archived model execution lost provider request"))?;
|
||||
if provider_request.request_id() != request_id
|
||||
|| provider_request != epiphany_openai_adapter::request_from_native(native_request)?
|
||||
|| provider_request != epiphany_model_adapter::request_from_native(native_request)?
|
||||
{
|
||||
return Err(anyhow!(
|
||||
"archived model execution request family is inconsistent"
|
||||
|
|
|
|||
|
|
@ -10,5 +10,9 @@ name = "epiphany_model_adapter"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
codex-connector = { git = "https://github.com/GameCult/CodexConnector", rev = "6dc80f6d266db4d82566d2434adcc55a48e8ecad", default-features = false }
|
||||
cultcache-rs = { path = "../vendor/cultcache-rs" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
sha2 = "0.10"
|
||||
|
|
|
|||
|
|
@ -1,192 +1,5 @@
|
|||
use cultcache_rs::DatabaseEntry;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
mod native;
|
||||
mod provider;
|
||||
|
||||
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.v1";
|
||||
#[derive(Debug, Clone, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "epiphany.model_request.v0", schema = "EpiphanyModelRequest")]
|
||||
pub struct EpiphanyModelRequest {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub conversation_id: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub provider: String,
|
||||
#[cultcache(key = 4)]
|
||||
pub model: String,
|
||||
#[cultcache(key = 5)]
|
||||
pub instructions: String,
|
||||
#[cultcache(key = 6, default)]
|
||||
pub input: Vec<EpiphanyModelInputItem>,
|
||||
#[cultcache(key = 7, default)]
|
||||
pub reasoning_effort: Option<String>,
|
||||
#[cultcache(key = 8, default)]
|
||||
pub reasoning_summary: Option<String>,
|
||||
#[cultcache(key = 9, default)]
|
||||
pub service_tier: Option<String>,
|
||||
#[cultcache(key = 10, default)]
|
||||
pub output_contract_id: Option<String>,
|
||||
#[cultcache(key = 11, default)]
|
||||
pub previous_response_id: Option<String>,
|
||||
#[cultcache(key = 12, default)]
|
||||
pub tools: Vec<EpiphanyModelToolDefinition>,
|
||||
#[cultcache(key = 13, default)]
|
||||
pub output_schema_json: Option<String>,
|
||||
#[cultcache(key = 14, default)]
|
||||
pub source_worker_job_id: Option<String>,
|
||||
#[cultcache(key = 15, default)]
|
||||
pub reasoning_basis_id: Option<String>,
|
||||
}
|
||||
|
||||
impl EpiphanyModelRequest {
|
||||
pub fn new(
|
||||
request_id: impl Into<String>,
|
||||
conversation_id: impl Into<String>,
|
||||
provider: impl Into<String>,
|
||||
model: impl Into<String>,
|
||||
instructions: impl Into<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
schema_id: MODEL_ADAPTER_REQUEST_SCHEMA_ID.to_string(),
|
||||
request_id: request_id.into(),
|
||||
conversation_id: conversation_id.into(),
|
||||
provider: provider.into(),
|
||||
model: model.into(),
|
||||
instructions: instructions.into(),
|
||||
input: Vec::new(),
|
||||
reasoning_effort: None,
|
||||
reasoning_summary: None,
|
||||
service_tier: None,
|
||||
output_contract_id: None,
|
||||
previous_response_id: None,
|
||||
tools: Vec::new(),
|
||||
output_schema_json: None,
|
||||
source_worker_job_id: None,
|
||||
reasoning_basis_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct EpiphanyModelToolDefinition {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub parameters_json: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum EpiphanyModelInputItem {
|
||||
UserText {
|
||||
text: String,
|
||||
},
|
||||
AssistantText {
|
||||
text: String,
|
||||
},
|
||||
ToolCall {
|
||||
call_id: String,
|
||||
name: String,
|
||||
arguments: String,
|
||||
},
|
||||
ToolResult {
|
||||
call_id: String,
|
||||
output: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(
|
||||
type = "epiphany.model_stream_event.v0",
|
||||
schema = "EpiphanyModelStreamEvent"
|
||||
)]
|
||||
pub struct EpiphanyModelStreamEvent {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub provider: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub sequence: u64,
|
||||
#[cultcache(key = 4)]
|
||||
pub payload: EpiphanyModelStreamPayload,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum EpiphanyModelStreamPayload {
|
||||
TextDelta {
|
||||
text: String,
|
||||
},
|
||||
ReasoningDelta {
|
||||
text: String,
|
||||
},
|
||||
ToolCall {
|
||||
call_id: String,
|
||||
name: String,
|
||||
arguments: String,
|
||||
},
|
||||
Completed {
|
||||
receipt: Box<EpiphanyModelReceipt>,
|
||||
},
|
||||
Failed {
|
||||
message: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
|
||||
#[cultcache(type = "epiphany.model_receipt.v1", schema = "EpiphanyModelReceipt")]
|
||||
pub struct EpiphanyModelReceipt {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub provider: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub model: String,
|
||||
#[cultcache(key = 4, default)]
|
||||
pub provider_response_id: Option<String>,
|
||||
#[cultcache(key = 5, default)]
|
||||
pub input_tokens: Option<u64>,
|
||||
#[cultcache(key = 6, default)]
|
||||
pub output_tokens: Option<u64>,
|
||||
#[cultcache(key = 7, default)]
|
||||
pub reasoning_output_tokens: Option<u64>,
|
||||
#[cultcache(key = 8, default)]
|
||||
pub transport: Option<String>,
|
||||
#[cultcache(key = 9, default)]
|
||||
pub caller_runtime_id: Option<String>,
|
||||
#[cultcache(key = 10, default)]
|
||||
pub native_request_sha256: Option<String>,
|
||||
#[cultcache(key = 11, default)]
|
||||
pub provider_request_sha256: Option<String>,
|
||||
#[cultcache(key = 12, default)]
|
||||
pub cached_input_tokens: Option<u64>,
|
||||
}
|
||||
|
||||
impl EpiphanyModelReceipt {
|
||||
pub fn new(
|
||||
request_id: impl Into<String>,
|
||||
provider: impl Into<String>,
|
||||
model: impl Into<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
schema_id: MODEL_ADAPTER_RECEIPT_SCHEMA_ID.to_string(),
|
||||
request_id: request_id.into(),
|
||||
provider: provider.into(),
|
||||
model: model.into(),
|
||||
provider_response_id: None,
|
||||
input_tokens: None,
|
||||
output_tokens: None,
|
||||
reasoning_output_tokens: None,
|
||||
transport: None,
|
||||
caller_runtime_id: None,
|
||||
native_request_sha256: None,
|
||||
provider_request_sha256: None,
|
||||
cached_input_tokens: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use native::*;
|
||||
pub use provider::*;
|
||||
|
|
|
|||
192
epiphany-model-adapter/src/native.rs
Normal file
192
epiphany-model-adapter/src/native.rs
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
use cultcache_rs::DatabaseEntry;
|
||||
use serde::Deserialize;
|
||||
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.v1";
|
||||
#[derive(Debug, Clone, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(type = "epiphany.model_request.v0", schema = "EpiphanyModelRequest")]
|
||||
pub struct EpiphanyModelRequest {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub conversation_id: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub provider: String,
|
||||
#[cultcache(key = 4)]
|
||||
pub model: String,
|
||||
#[cultcache(key = 5)]
|
||||
pub instructions: String,
|
||||
#[cultcache(key = 6, default)]
|
||||
pub input: Vec<EpiphanyModelInputItem>,
|
||||
#[cultcache(key = 7, default)]
|
||||
pub reasoning_effort: Option<String>,
|
||||
#[cultcache(key = 8, default)]
|
||||
pub reasoning_summary: Option<String>,
|
||||
#[cultcache(key = 9, default)]
|
||||
pub service_tier: Option<String>,
|
||||
#[cultcache(key = 10, default)]
|
||||
pub output_contract_id: Option<String>,
|
||||
#[cultcache(key = 11, default)]
|
||||
pub previous_response_id: Option<String>,
|
||||
#[cultcache(key = 12, default)]
|
||||
pub tools: Vec<EpiphanyModelToolDefinition>,
|
||||
#[cultcache(key = 13, default)]
|
||||
pub output_schema_json: Option<String>,
|
||||
#[cultcache(key = 14, default)]
|
||||
pub source_worker_job_id: Option<String>,
|
||||
#[cultcache(key = 15, default)]
|
||||
pub reasoning_basis_id: Option<String>,
|
||||
}
|
||||
|
||||
impl EpiphanyModelRequest {
|
||||
pub fn new(
|
||||
request_id: impl Into<String>,
|
||||
conversation_id: impl Into<String>,
|
||||
provider: impl Into<String>,
|
||||
model: impl Into<String>,
|
||||
instructions: impl Into<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
schema_id: MODEL_ADAPTER_REQUEST_SCHEMA_ID.to_string(),
|
||||
request_id: request_id.into(),
|
||||
conversation_id: conversation_id.into(),
|
||||
provider: provider.into(),
|
||||
model: model.into(),
|
||||
instructions: instructions.into(),
|
||||
input: Vec::new(),
|
||||
reasoning_effort: None,
|
||||
reasoning_summary: None,
|
||||
service_tier: None,
|
||||
output_contract_id: None,
|
||||
previous_response_id: None,
|
||||
tools: Vec::new(),
|
||||
output_schema_json: None,
|
||||
source_worker_job_id: None,
|
||||
reasoning_basis_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct EpiphanyModelToolDefinition {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub parameters_json: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum EpiphanyModelInputItem {
|
||||
UserText {
|
||||
text: String,
|
||||
},
|
||||
AssistantText {
|
||||
text: String,
|
||||
},
|
||||
ToolCall {
|
||||
call_id: String,
|
||||
name: String,
|
||||
arguments: String,
|
||||
},
|
||||
ToolResult {
|
||||
call_id: String,
|
||||
output: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, DatabaseEntry)]
|
||||
#[cultcache(
|
||||
type = "epiphany.model_stream_event.v0",
|
||||
schema = "EpiphanyModelStreamEvent"
|
||||
)]
|
||||
pub struct EpiphanyModelStreamEvent {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub provider: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub sequence: u64,
|
||||
#[cultcache(key = 4)]
|
||||
pub payload: EpiphanyModelStreamPayload,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum EpiphanyModelStreamPayload {
|
||||
TextDelta {
|
||||
text: String,
|
||||
},
|
||||
ReasoningDelta {
|
||||
text: String,
|
||||
},
|
||||
ToolCall {
|
||||
call_id: String,
|
||||
name: String,
|
||||
arguments: String,
|
||||
},
|
||||
Completed {
|
||||
receipt: Box<EpiphanyModelReceipt>,
|
||||
},
|
||||
Failed {
|
||||
message: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, DatabaseEntry)]
|
||||
#[cultcache(type = "epiphany.model_receipt.v1", schema = "EpiphanyModelReceipt")]
|
||||
pub struct EpiphanyModelReceipt {
|
||||
#[cultcache(key = 0)]
|
||||
pub schema_id: String,
|
||||
#[cultcache(key = 1)]
|
||||
pub request_id: String,
|
||||
#[cultcache(key = 2)]
|
||||
pub provider: String,
|
||||
#[cultcache(key = 3)]
|
||||
pub model: String,
|
||||
#[cultcache(key = 4, default)]
|
||||
pub provider_response_id: Option<String>,
|
||||
#[cultcache(key = 5, default)]
|
||||
pub input_tokens: Option<u64>,
|
||||
#[cultcache(key = 6, default)]
|
||||
pub output_tokens: Option<u64>,
|
||||
#[cultcache(key = 7, default)]
|
||||
pub reasoning_output_tokens: Option<u64>,
|
||||
#[cultcache(key = 8, default)]
|
||||
pub transport: Option<String>,
|
||||
#[cultcache(key = 9, default)]
|
||||
pub caller_runtime_id: Option<String>,
|
||||
#[cultcache(key = 10, default)]
|
||||
pub native_request_sha256: Option<String>,
|
||||
#[cultcache(key = 11, default)]
|
||||
pub provider_request_sha256: Option<String>,
|
||||
#[cultcache(key = 12, default)]
|
||||
pub cached_input_tokens: Option<u64>,
|
||||
}
|
||||
|
||||
impl EpiphanyModelReceipt {
|
||||
pub fn new(
|
||||
request_id: impl Into<String>,
|
||||
provider: impl Into<String>,
|
||||
model: impl Into<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
schema_id: MODEL_ADAPTER_RECEIPT_SCHEMA_ID.to_string(),
|
||||
request_id: request_id.into(),
|
||||
provider: provider.into(),
|
||||
model: model.into(),
|
||||
provider_response_id: None,
|
||||
input_tokens: None,
|
||||
output_tokens: None,
|
||||
reasoning_output_tokens: None,
|
||||
transport: None,
|
||||
caller_runtime_id: None,
|
||||
native_request_sha256: None,
|
||||
provider_request_sha256: None,
|
||||
cached_input_tokens: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
use anyhow::{Result, anyhow};
|
||||
use codex_connector::{CodexInputItem, CodexProviderRequest, CodexToolChoice, CodexToolDefinition};
|
||||
use cultcache_rs::DatabaseEntry;
|
||||
use epiphany_model_adapter::{
|
||||
use crate::{
|
||||
EpiphanyModelInputItem, EpiphanyModelReceipt, EpiphanyModelRequest, EpiphanyModelStreamEvent,
|
||||
EpiphanyModelStreamPayload, EpiphanyModelToolDefinition, MODEL_ADAPTER_EVENT_SCHEMA_ID,
|
||||
};
|
||||
use anyhow::{Result, anyhow};
|
||||
use codex_connector::{CodexInputItem, CodexProviderRequest, CodexToolChoice, CodexToolDefinition};
|
||||
use cultcache_rs::DatabaseEntry;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
[package]
|
||||
name = "epiphany-openai-adapter"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
license-file = "../LICENSE"
|
||||
|
||||
[lib]
|
||||
name = "epiphany_openai_adapter"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
codex-connector = { git = "https://github.com/GameCult/CodexConnector", rev = "6dc80f6d266db4d82566d2434adcc55a48e8ecad", default-features = false }
|
||||
cultcache-rs = { path = "../vendor/cultcache-rs" }
|
||||
epiphany-model-adapter = { path = "../epiphany-model-adapter" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
sha2 = "0.10"
|
||||
|
|
@ -16,7 +16,6 @@ chrono = "0.4.44"
|
|||
cultcache-rs = { path = "../vendor/cultcache-rs" }
|
||||
epiphany-core = { path = "../epiphany-core" }
|
||||
epiphany-model-adapter = { path = "../epiphany-model-adapter" }
|
||||
epiphany-openai-adapter = { path = "../epiphany-openai-adapter" }
|
||||
epiphany-tool-adapter = { path = "../epiphany-tool-adapter" }
|
||||
rmp-serde = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use epiphany_model_adapter::{
|
|||
MODEL_ADAPTER_EVENT_SCHEMA_ID,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use epiphany_openai_adapter::{EpiphanyOpenRouterRequest, EpiphanyProviderRequestPayload};
|
||||
use epiphany_model_adapter::{EpiphanyOpenRouterRequest, EpiphanyProviderRequestPayload};
|
||||
use epiphany_openai_runtime::DEFAULT_CODEX_CONNECTOR_ENDPOINT;
|
||||
use epiphany_openai_runtime::DEFAULT_PROVIDER_REQUEST_TIMEOUT;
|
||||
use epiphany_openai_runtime::EpiphanyOpenAiRuntimeOptions;
|
||||
|
|
@ -934,7 +934,7 @@ mod tests {
|
|||
output: r#"{"ok":true}"#.into(),
|
||||
});
|
||||
|
||||
let projected = epiphany_openai_adapter::request_from_native(&request)?;
|
||||
let projected = epiphany_model_adapter::request_from_native(&request)?;
|
||||
let EpiphanyProviderRequestPayload::Codex(projected) = projected.payload else {
|
||||
panic!("Codex provider must lower to the connector contract")
|
||||
};
|
||||
|
|
@ -1048,7 +1048,7 @@ mod tests {
|
|||
);
|
||||
request.output_contract_id = Some(format!("worker-schema-{index}"));
|
||||
request.output_schema_json = Some(serde_json::to_string(&schema)?);
|
||||
let projected = epiphany_openai_adapter::strict_provider_schema(
|
||||
let projected = epiphany_model_adapter::strict_provider_schema(
|
||||
request.output_schema_json.as_deref().unwrap(),
|
||||
)?;
|
||||
assert_eq!(projected["additionalProperties"], false);
|
||||
|
|
@ -1072,7 +1072,7 @@ mod tests {
|
|||
),
|
||||
)?);
|
||||
|
||||
let projected = epiphany_openai_adapter::strict_provider_schema(
|
||||
let projected = epiphany_model_adapter::strict_provider_schema(
|
||||
request.output_schema_json.as_deref().unwrap(),
|
||||
)?;
|
||||
let decision = &projected["properties"]["researchDecision"];
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ use epiphany_model_adapter::EpiphanyModelRequest;
|
|||
use epiphany_model_adapter::EpiphanyModelStreamEvent;
|
||||
use epiphany_model_adapter::EpiphanyModelStreamPayload;
|
||||
use epiphany_model_adapter::EpiphanyModelToolDefinition;
|
||||
use epiphany_openai_adapter::EpiphanyProviderRequest;
|
||||
use epiphany_model_adapter::EpiphanyProviderRequest;
|
||||
use epiphany_tool_adapter::EPIPHANY_TOOL_RUNTIME_ADAPTER_ID;
|
||||
use epiphany_tool_adapter::EpiphanyToolInvocationIntent;
|
||||
use epiphany_tool_adapter::EpiphanyToolInvocationReceipt;
|
||||
|
|
@ -765,7 +765,7 @@ pub fn model_receipt_key(request_id: &str) -> String {
|
|||
pub fn provider_request_from_model_request(
|
||||
request: &EpiphanyModelRequest,
|
||||
) -> Result<EpiphanyProviderRequest> {
|
||||
epiphany_openai_adapter::request_from_native(request)
|
||||
epiphany_model_adapter::request_from_native(request)
|
||||
}
|
||||
|
||||
fn repository_source_tools() -> Vec<EpiphanyModelToolDefinition> {
|
||||
|
|
@ -2772,7 +2772,7 @@ mod tests {
|
|||
"gpt-5.4",
|
||||
"Answer plainly.",
|
||||
);
|
||||
let request = epiphany_openai_adapter::request_from_native(&native_request)?;
|
||||
let request = epiphany_model_adapter::request_from_native(&native_request)?;
|
||||
let options = default_options(store.clone(), &request);
|
||||
ensure_openai_runtime_ready(&options)?;
|
||||
open_runtime_model_execution(
|
||||
|
|
@ -3220,7 +3220,7 @@ mod tests {
|
|||
r#"{"type":"object","properties":{"researchDecision":{"type":"string"}},"required":["researchDecision"]}"#
|
||||
.to_string(),
|
||||
);
|
||||
let request = epiphany_openai_adapter::request_from_native(&native_request)?;
|
||||
let request = epiphany_model_adapter::request_from_native(&native_request)?;
|
||||
let options = default_options(store.clone(), &request);
|
||||
ensure_openai_runtime_ready(&options)?;
|
||||
open_runtime_model_execution(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use epiphany_model_adapter::{
|
|||
EpiphanyModelReceipt, EpiphanyModelRequest, EpiphanyModelStreamEvent,
|
||||
EpiphanyModelStreamPayload, MODEL_ADAPTER_EVENT_SCHEMA_ID,
|
||||
};
|
||||
use epiphany_openai_adapter::{
|
||||
use epiphany_model_adapter::{
|
||||
EpiphanyOpenRouterRequest, EpiphanyProviderRequestPayload, openrouter_events_from_response,
|
||||
openrouter_request_body,
|
||||
};
|
||||
|
|
|
|||
Reference in a new issue