mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
migrate ai format conversion to responses adapters
This commit is contained in:
@@ -39,7 +39,7 @@ impl MinimalCandidateSelectionReadRepository for InMemoryMinimalCandidateSelecti
|
||||
&& row.key_is_active
|
||||
&& row.model_is_active
|
||||
&& row.model_is_available
|
||||
&& row.endpoint_api_format.eq_ignore_ascii_case(api_format)
|
||||
&& api_format_matches(&row.endpoint_api_format, api_format)
|
||||
&& row.key_supports_api_format(api_format)
|
||||
})
|
||||
.cloned()
|
||||
@@ -69,6 +69,18 @@ impl MinimalCandidateSelectionReadRepository for InMemoryMinimalCandidateSelecti
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_api_format(value: &str) -> String {
|
||||
match value.trim().to_ascii_lowercase().as_str() {
|
||||
"openai:cli" => "openai:responses".to_string(),
|
||||
"openai:compact" => "openai:responses:compact".to_string(),
|
||||
other => other.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn api_format_matches(left: &str, right: &str) -> bool {
|
||||
normalize_api_format(left) == normalize_api_format(right)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::InMemoryMinimalCandidateSelectionReadRepository;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use async_trait::async_trait;
|
||||
use futures_util::{stream::TryStream, TryStreamExt};
|
||||
use sqlx::{PgPool, Row};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use super::{
|
||||
MinimalCandidateSelectionReadRepository, StoredMinimalCandidateSelectionRow,
|
||||
@@ -226,13 +227,19 @@ impl SqlxMinimalCandidateSelectionReadRepository {
|
||||
&self,
|
||||
api_format: &str,
|
||||
) -> Result<Vec<StoredMinimalCandidateSelectionRow>, DataLayerError> {
|
||||
Self::collect_query_rows(
|
||||
sqlx::query(LIST_FOR_EXACT_API_FORMAT_SQL)
|
||||
.bind(api_format)
|
||||
.fetch(&self.pool),
|
||||
map_candidate_selection_row,
|
||||
)
|
||||
.await
|
||||
let mut rows = Vec::new();
|
||||
for api_format in api_format_aliases(api_format) {
|
||||
rows.extend(
|
||||
Self::collect_query_rows(
|
||||
sqlx::query(LIST_FOR_EXACT_API_FORMAT_SQL)
|
||||
.bind(api_format)
|
||||
.fetch(&self.pool),
|
||||
map_candidate_selection_row,
|
||||
)
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
Ok(dedupe_candidate_selection_rows(rows))
|
||||
}
|
||||
|
||||
pub async fn list_for_exact_api_format_and_global_model(
|
||||
@@ -240,17 +247,48 @@ impl SqlxMinimalCandidateSelectionReadRepository {
|
||||
api_format: &str,
|
||||
global_model_name: &str,
|
||||
) -> Result<Vec<StoredMinimalCandidateSelectionRow>, DataLayerError> {
|
||||
Self::collect_query_rows(
|
||||
sqlx::query(LIST_FOR_EXACT_API_FORMAT_AND_GLOBAL_MODEL_SQL)
|
||||
.bind(api_format)
|
||||
.bind(global_model_name)
|
||||
.fetch(&self.pool),
|
||||
map_candidate_selection_row,
|
||||
)
|
||||
.await
|
||||
let mut rows = Vec::new();
|
||||
for api_format in api_format_aliases(api_format) {
|
||||
rows.extend(
|
||||
Self::collect_query_rows(
|
||||
sqlx::query(LIST_FOR_EXACT_API_FORMAT_AND_GLOBAL_MODEL_SQL)
|
||||
.bind(api_format)
|
||||
.bind(global_model_name)
|
||||
.fetch(&self.pool),
|
||||
map_candidate_selection_row,
|
||||
)
|
||||
.await?,
|
||||
);
|
||||
}
|
||||
Ok(dedupe_candidate_selection_rows(rows))
|
||||
}
|
||||
}
|
||||
|
||||
fn api_format_aliases(api_format: &str) -> Vec<&str> {
|
||||
match api_format.trim().to_ascii_lowercase().as_str() {
|
||||
"openai:responses" => vec!["openai:responses", "openai:cli"],
|
||||
"openai:cli" => vec!["openai:responses", "openai:cli"],
|
||||
"openai:responses:compact" => vec!["openai:responses:compact", "openai:compact"],
|
||||
"openai:compact" => vec!["openai:responses:compact", "openai:compact"],
|
||||
_ => vec![api_format],
|
||||
}
|
||||
}
|
||||
|
||||
fn dedupe_candidate_selection_rows(
|
||||
rows: Vec<StoredMinimalCandidateSelectionRow>,
|
||||
) -> Vec<StoredMinimalCandidateSelectionRow> {
|
||||
let mut seen = BTreeSet::new();
|
||||
rows.into_iter()
|
||||
.filter(|row| {
|
||||
seen.insert((
|
||||
row.endpoint_id.clone(),
|
||||
row.key_id.clone(),
|
||||
row.model_id.clone(),
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl MinimalCandidateSelectionReadRepository for SqlxMinimalCandidateSelectionReadRepository {
|
||||
async fn list_for_exact_api_format(
|
||||
|
||||
@@ -595,7 +595,7 @@ mod tests {
|
||||
latency_ms: Some(25),
|
||||
concurrent_requests: Some(2),
|
||||
extra_data: Some(json!({
|
||||
"provider_api_format": "openai:cli",
|
||||
"provider_api_format": "openai:responses",
|
||||
"provider_name": "updated",
|
||||
})),
|
||||
required_capabilities: None,
|
||||
@@ -621,7 +621,7 @@ mod tests {
|
||||
.extra_data
|
||||
.as_ref()
|
||||
.and_then(|value| value.get("provider_api_format")),
|
||||
Some(&json!("openai:cli"))
|
||||
Some(&json!("openai:responses"))
|
||||
);
|
||||
assert_eq!(
|
||||
updated
|
||||
|
||||
Reference in New Issue
Block a user