Merge commit 'refs/pull/481/head' of github-fawney19:fawney19/Aether

# Conflicts:
#	apps/aether-gateway/src/ai_serving/api.rs
#	apps/aether-gateway/src/ai_serving/planner/standard/family/request.rs
#	apps/aether-gateway/src/ai_serving/planner/standard/openai/chat/decision/request.rs
#	apps/aether-gateway/src/ai_serving/planner/standard/openai/responses/decision/request.rs
This commit is contained in:
fawney19
2026-05-19 01:46:41 +08:00
124 changed files with 14402 additions and 702 deletions

View File

@@ -316,6 +316,13 @@ fn key_auth_channel_matches(row: &StoredMinimalCandidateSelectionRow, api_format
"gemini_cli" | "antigravity" => {
auth_type == "oauth" && api_format == "gemini:generate_content"
}
"grok" => {
auth_type == "oauth"
&& matches!(
api_format.as_str(),
"openai:chat" | "openai:responses" | "claude:messages" | "openai:image"
)
}
"vertex_ai" => {
(auth_type == "api_key" && api_format == "gemini:generate_content")
|| (matches!(auth_type.as_str(), "service_account" | "vertex_ai")
@@ -419,6 +426,35 @@ mod tests {
assert_eq!(rows[0].provider_id, "provider-1");
}
#[tokio::test]
async fn includes_grok_oauth_rows_for_chat_models() {
let mut row = sample_row(
"provider-grok",
"openai:chat",
"grok-4.20-0309-non-reasoning",
10,
);
row.provider_type = "grok".to_string();
row.provider_name = "grok".to_string();
row.key_auth_type = "oauth".to_string();
row.key_api_formats = Some(vec![
"openai:chat".to_string(),
"openai:responses".to_string(),
"claude:messages".to_string(),
"openai:image".to_string(),
]);
let repository = InMemoryMinimalCandidateSelectionReadRepository::seed(vec![row]);
let rows = repository
.list_for_exact_api_format("openai:chat")
.await
.expect("list should succeed");
assert_eq!(rows.len(), 1);
assert_eq!(rows[0].provider_type, "grok");
assert_eq!(rows[0].global_model_name, "grok-4.20-0309-non-reasoning");
}
#[tokio::test]
async fn requested_model_filter_respects_endpoint_scoped_default_mapping() {
let mut selected = sample_row("provider-1", "openai:chat", "deepseek-v4-pro", 10);

View File

@@ -445,6 +445,13 @@ fn key_auth_channel_matches(row: &CandidateSelectionRow, api_format: &str) -> bo
"gemini_cli" | "antigravity" => {
auth_type == "oauth" && api_format == "gemini:generate_content"
}
"grok" => {
auth_type == "oauth"
&& matches!(
api_format.as_str(),
"openai:chat" | "openai:responses" | "claude:messages" | "openai:image"
)
}
"vertex_ai" => {
(auth_type == "api_key" && api_format == "gemini:generate_content")
|| (matches!(auth_type.as_str(), "service_account" | "vertex_ai")

View File

@@ -103,6 +103,11 @@ WHERE p.is_active = TRUE
)
)
)
OR (
LOWER(BTRIM(p.provider_type)) = 'grok'
AND LOWER(BTRIM(pak.auth_type)) = 'oauth'
AND LOWER($3) IN ('openai:chat', 'openai:responses', 'claude:messages', 'openai:image')
)
OR (
LOWER(BTRIM(p.provider_type)) IN ('gemini_cli', 'antigravity')
AND LOWER(BTRIM(pak.auth_type)) = 'oauth'
@@ -127,6 +132,7 @@ WHERE p.is_active = TRUE
'claude_code',
'codex',
'gemini_cli',
'grok',
'vertex_ai',
'antigravity',
'kiro'
@@ -286,6 +292,11 @@ WHERE p.is_active = TRUE
)
)
)
OR (
LOWER(BTRIM(p.provider_type)) = 'grok'
AND LOWER(BTRIM(pak.auth_type)) = 'oauth'
AND LOWER($4) IN ('openai:chat', 'openai:responses', 'claude:messages', 'openai:image')
)
OR (
LOWER(BTRIM(p.provider_type)) IN ('gemini_cli', 'antigravity')
AND LOWER(BTRIM(pak.auth_type)) = 'oauth'
@@ -310,6 +321,7 @@ WHERE p.is_active = TRUE
'claude_code',
'codex',
'gemini_cli',
'grok',
'vertex_ai',
'antigravity',
'kiro'
@@ -468,6 +480,11 @@ WHERE p.is_active = TRUE
)
)
)
OR (
LOWER(BTRIM(p.provider_type)) = 'grok'
AND LOWER(BTRIM(pak.auth_type)) = 'oauth'
AND LOWER($6) IN ('openai:chat', 'openai:responses', 'claude:messages', 'openai:image')
)
OR (
LOWER(BTRIM(p.provider_type)) IN ('gemini_cli', 'antigravity')
AND LOWER(BTRIM(pak.auth_type)) = 'oauth'
@@ -492,6 +509,7 @@ WHERE p.is_active = TRUE
'claude_code',
'codex',
'gemini_cli',
'grok',
'vertex_ai',
'antigravity',
'kiro'
@@ -1287,6 +1305,23 @@ mod tests {
}
}
#[test]
fn candidate_selection_sql_allows_grok_oauth_chat_auth() {
let requested_model_sql = requested_model_selection_sql();
for sql in [
LIST_FOR_EXACT_API_FORMAT_SQL,
LIST_FOR_EXACT_API_FORMAT_AND_GLOBAL_MODEL_SQL,
LIST_POOL_KEYS_FOR_GROUP_SQL,
requested_model_sql.as_str(),
] {
assert!(sql.contains("LOWER(BTRIM(p.provider_type)) = 'grok'"));
assert!(sql.contains("LOWER(BTRIM(pak.auth_type)) = 'oauth'"));
assert!(sql
.contains("'openai:chat', 'openai:responses', 'claude:messages', 'openai:image'"));
assert!(sql.contains("'grok',"));
}
}
#[test]
fn requested_model_selection_page_sql_adds_limit_and_offset() {
let sql = requested_model_selection_page_sql();

View File

@@ -824,6 +824,13 @@ fn key_auth_channel_matches(row: &CandidateSelectionRow, api_format: &str) -> bo
"gemini_cli" | "antigravity" => {
auth_type == "oauth" && api_format == "gemini:generate_content"
}
"grok" => {
auth_type == "oauth"
&& matches!(
api_format.as_str(),
"openai:chat" | "openai:responses" | "claude:messages" | "openai:image"
)
}
"vertex_ai" => {
(auth_type == "api_key" && api_format == "gemini:generate_content")
|| (matches!(auth_type.as_str(), "service_account" | "vertex_ai")