2026-05-16 19:22:54 +08:00
use std ::collections ::BTreeMap ;
use aether_contracts ::{
ResolvedTransportProfile , TRANSPORT_BACKEND_BROWSER_WREQ , TRANSPORT_HTTP_MODE_AUTO ,
TRANSPORT_POOL_SCOPE_KEY ,
};
use serde_json ::Value ;
use serde_json ::{ json , Map };
use uuid ::Uuid ;
use crate ::rules ::apply_local_header_rules_with_request_headers ;
use crate ::snapshot ::GatewayProviderTransportSnapshot ;
pub const GROK_INTERNAL_HEADER : & str = "x-aether-grok-runtime" ;
pub const GROK_DEFAULT_BASE_URL : & str = "https://grok.com" ;
pub const GROK_CHAT_PATH : & str = "/rest/app-chat/conversations/new" ;
pub const GROK_RATE_LIMITS_PATH : & str = "/rest/rate-limits" ;
pub const GROK_IMAGE_EDIT_MODEL_NAME : & str = "imagine-image-edit" ;
pub const GROK_IMAGE_EDIT_MODEL_KIND : & str = "imagine" ;
pub const GROK_DEFAULT_BROWSER_PROFILE : & str = "chrome136" ;
pub const GROK_DEFAULT_USER_AGENT : & str = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36" ;
const GROK_IMAGE_GENERATION_MAX_COUNT : u64 = 4 ;
const GROK_SEC_CH_UA_PLATFORM : & str = r #""macOS""# ;
const GROK_STATSIG_ID : & str = "ZTpUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkIChyZWFkaW5nICdjaGlsZE5vZGVzJyk=" ;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GrokBrowserProfileMetadata {
pub profile_id : String ,
pub browser_profile : String ,
pub user_agent : String ,
pub sec_ch_ua : String ,
pub sec_ch_ua_platform : String ,
}
#[derive(Debug, Clone)]
pub struct GrokHeaderInput < 'a > {
pub transport : & 'a GatewayProviderTransportSnapshot ,
pub transport_profile : Option <& 'a ResolvedTransportProfile > ,
pub request_headers : Option <& 'a http ::HeaderMap > ,
pub content_type : & 'a str ,
pub accept : & 'a str ,
pub header_rules : Option <& 'a Value > ,
pub provider_request_body : & 'a Value ,
pub original_request_body : & 'a Value ,
}
pub fn is_grok_provider_transport ( transport : & GatewayProviderTransportSnapshot ) -> bool {
transport
. provider
. provider_type
. trim ()
. eq_ignore_ascii_case ( "grok" )
}
pub fn grok_base_url ( base_url : & str ) -> String {
let base_url = base_url . trim (). trim_end_matches ( '/' );
if base_url . is_empty () {
GROK_DEFAULT_BASE_URL . to_string ()
} else {
base_url . to_string ()
}
}
pub fn build_grok_upstream_url ( transport : & GatewayProviderTransportSnapshot , path : & str ) -> String {
let base_url = grok_base_url ( & transport . endpoint . base_url );
let path = path . trim ();
if path . starts_with ( '/' ) {
format! ( " {base_url}{path} " )
} else {
format! ( " {base_url} / {path} " )
}
}
pub fn resolve_grok_session_auth (
transport : & GatewayProviderTransportSnapshot ,
) -> Option < ( String , String ) > {
let cookie = grok_cookie_from_transport ( transport ) ? ;
Some (( "cookie" . to_string (), cookie ))
}
pub fn grok_browser_profile_metadata (
profile_id : Option <& str > ,
) -> Option < GrokBrowserProfileMetadata > {
let raw = profile_id
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. unwrap_or ( GROK_DEFAULT_BROWSER_PROFILE );
let normalized = raw . trim (). to_ascii_lowercase (). replace ([ '_' , '-' , ' ' ], "" );
let version = supported_grok_chrome_profile_version ( & normalized ) ? ;
let profile_id = format! ( "chrome {version} " );
Some ( GrokBrowserProfileMetadata {
profile_id : profile_id . clone (),
browser_profile : profile_id ,
user_agent : format ! (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{version}.0.0.0 Safari/537.36"
),
sec_ch_ua : format ! (
r #""Google Chrome";v="{version}", "Chromium";v="{version}", "Not(A:Brand";v="24""#
),
sec_ch_ua_platform : GROK_SEC_CH_UA_PLATFORM . to_string (),
})
}
pub fn grok_browser_profile_id_from_user_agent ( user_agent : & str ) -> Option < String > {
chrome_major_version_from_user_agent ( user_agent , "Chrome/" )
. or_else ( || chrome_major_version_from_user_agent ( user_agent , "Chromium/" ))
. and_then ( | version | supported_grok_chrome_profile_version ( & format! ( "chrome {version} " )))
. map ( | version | format! ( "chrome {version} " ))
}
pub fn grok_browser_profile_metadata_from_resolved_transport_profile (
profile : & ResolvedTransportProfile ,
) -> Option < GrokBrowserProfileMetadata > {
if ! profile
. backend
. trim ()
. eq_ignore_ascii_case ( TRANSPORT_BACKEND_BROWSER_WREQ )
{
return None ;
}
let profile_id = profile
. extra
. as_ref ()
. and_then ( | value | value . get ( "browser_profile" ))
. and_then ( Value ::as_str )
. or ( Some ( profile . profile_id . as_str ()));
grok_browser_profile_metadata ( profile_id )
}
pub fn grok_browser_resolved_transport_profile_from_auth_config (
auth_config : & Map < String , Value > ,
source : & str ,
) -> Option < ResolvedTransportProfile > {
let browser_profile = grok_browser_profile_id_from_auth_config ( auth_config ) ? ;
grok_browser_resolved_transport_profile ( browser_profile . as_deref (), source )
}
pub fn grok_browser_resolved_transport_profile (
profile_id : Option <& str > ,
source : & str ,
) -> Option < ResolvedTransportProfile > {
let metadata = grok_browser_profile_metadata ( profile_id ) ? ;
Some ( ResolvedTransportProfile {
profile_id : metadata . profile_id . clone (),
backend : TRANSPORT_BACKEND_BROWSER_WREQ . to_string (),
http_mode : TRANSPORT_HTTP_MODE_AUTO . to_string (),
pool_scope : TRANSPORT_POOL_SCOPE_KEY . to_string (),
header_fingerprint : None ,
extra : Some ( json! ({
"browser_profile" : metadata . browser_profile ,
"source" : source ,
})),
})
}
pub fn grok_browser_transport_fingerprint_from_auth_config (
auth_config : & Map < String , Value > ,
) -> Option < Value > {
let transport_profile =
grok_browser_resolved_transport_profile_from_auth_config ( auth_config , "grok_import" ) ? ;
Some ( json! ({ "transport_profile" : transport_profile }))
}
fn grok_browser_profile_id_from_auth_config (
auth_config : & Map < String , Value > ,
) -> Option < Option < String >> {
if let Some ( browser_profile ) = grok_config_string_from_object (
Some ( auth_config ),
& [
"browser_profile" ,
"browserProfile" ,
"browser" ,
"impersonate" ,
],
) {
return Some ( Some ( browser_profile ));
}
let Some ( user_agent ) =
grok_config_string_from_object ( Some ( auth_config ), & [ "user_agent" , "userAgent" ])
else {
return Some ( None );
};
grok_browser_profile_id_from_user_agent ( & user_agent ). map ( Some )
}
fn chrome_major_version_from_user_agent ( user_agent : & str , marker : & str ) -> Option < u16 > {
let user_agent_lower = user_agent . to_ascii_lowercase ();
let marker_lower = marker . to_ascii_lowercase ();
let index = user_agent_lower . find ( & marker_lower ) ? ;
let version_start = index + marker . len ();
let digits = user_agent [ version_start .. ]
. chars ()
. take_while ( | ch | ch . is_ascii_digit ())
. collect ::< String > ();
( ! digits . is_empty ())
. then_some ( digits )
. and_then ( | digits | digits . parse ::< u16 > (). ok ())
}
fn supported_grok_chrome_profile_version ( normalized : & str ) -> Option < u16 > {
let version = normalized . strip_prefix ( "chrome" ) ? . parse ::< u16 > (). ok () ? ;
match version {
100 | 101 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 114 | 116 | 117 | 118 | 119 | 120
| 123 | 124 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137
| 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 => Some ( version ),
_ => None ,
}
}
pub fn build_grok_browser_headers ( input : GrokHeaderInput < '_ > ) -> Option < BTreeMap < String , String >> {
let cookie = grok_cookie_from_transport ( input . transport ) ? ;
let base_url = grok_base_url ( & input . transport . endpoint . base_url );
let browser_profile =
grok_browser_profile_metadata_from_resolved_transport_profile ( input . transport_profile ? ) ? ;
let mut headers = BTreeMap ::from ([
( "accept" . to_string (), input . accept . to_string ()),
(
"accept-language" . to_string (),
"zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7" . to_string (),
),
(
"baggage" . to_string (),
"sentry-environment=production,sentry-release=d6add6fb0460641fd482d767a335ef72b9b6abb8,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c" . to_string (),
),
( "content-type" . to_string (), input . content_type . to_string ()),
( "cookie" . to_string (), cookie ),
( GROK_INTERNAL_HEADER . to_string (), "1" . to_string ()),
( "origin" . to_string (), base_url . clone ()),
( "priority" . to_string (), "u=1, i" . to_string ()),
( "referer" . to_string (), format! ( " {base_url} /" )),
( "sec-ch-ua" . to_string (), browser_profile . sec_ch_ua ),
( "sec-ch-ua-mobile" . to_string (), "?0" . to_string ()),
(
"sec-ch-ua-platform" . to_string (),
browser_profile . sec_ch_ua_platform ,
),
( "sec-fetch-dest" . to_string (), "empty" . to_string ()),
( "sec-fetch-mode" . to_string (), "cors" . to_string ()),
( "sec-fetch-site" . to_string (), "same-origin" . to_string ()),
( "user-agent" . to_string (), browser_profile . user_agent ),
( "x-statsig-id" . to_string (), GROK_STATSIG_ID . to_string ()),
( "x-xai-request-id" . to_string (), Uuid ::new_v4 (). to_string ()),
]);
if ! apply_local_header_rules_with_request_headers (
& mut headers ,
input . header_rules ,
& [ "cookie" , "content-type" , "accept" , GROK_INTERNAL_HEADER ],
input . provider_request_body ,
Some ( input . original_request_body ),
input . request_headers ,
) {
return None ;
}
Some ( headers )
}
pub fn build_grok_app_chat_body (
client_api_format : & str ,
model : Option <& str > ,
original_body : & Value ,
) -> Value {
let model = model . map ( str ::trim ). filter ( | value | ! value . is_empty ());
let client_api_format = client_api_format . trim (). to_ascii_lowercase ();
if client_api_format . eq_ignore_ascii_case ( "openai:image" )
&& grok_is_image_edit_request ( original_body )
{
return build_grok_image_edit_body ( original_body );
}
let is_image_generation =
grok_is_image_generation_request ( client_api_format . as_str (), model , original_body );
let message = if is_image_generation {
extract_grok_image_prompt ( original_body )
. map ( | prompt | format! ( "Drawing: {prompt} " ))
. unwrap_or_else ( || "Drawing:" . to_string ())
} else {
match client_api_format . as_str () {
"openai:responses" | "openai:responses:compact" => {
extract_grok_message_from_openai_responses_body ( original_body )
}
"claude:messages" => extract_grok_message_from_claude_messages_body ( original_body ),
_ => extract_grok_message_from_openai_chat_body ( original_body ),
}
};
let mut payload = grok_base_app_chat_payload ( message , grok_mode_id_for_model ( model ));
if is_image_generation {
payload . insert (
"imageGenerationCount" . to_string (),
json! ( extract_grok_image_count ( original_body )
. unwrap_or ( 1 )
. clamp ( 1 , GROK_IMAGE_GENERATION_MAX_COUNT )),
);
if let Some ( size ) = extract_grok_image_option (
original_body ,
& [ "aspect_ratio" , "aspectRatio" , "ratio" , "size" ],
) {
payload . insert ( "size" . to_string (), Value ::String ( size ));
}
}
Value ::Object ( payload )
}
fn grok_is_image_generation_request (
client_api_format : & str ,
model : Option <& str > ,
body : & Value ,
) -> bool {
if client_api_format . eq_ignore_ascii_case ( "openai:image" ) {
return ! grok_is_image_edit_request ( body );
}
if ! matches! (
client_api_format ,
"openai:chat" | "openai:responses" | "openai:responses:compact"
) {
return false ;
}
grok_is_image_generation_model ( model ) || grok_has_image_generation_tool ( body )
}
fn grok_is_image_generation_model ( model : Option <& str > ) -> bool {
let model = model . unwrap_or_default (). trim (). to_ascii_lowercase ();
model . contains ( "grok-imagine-image" ) && ! model . contains ( "edit" )
}
fn grok_has_image_generation_tool ( body : & Value ) -> bool {
body . get ( "tools" )
. and_then ( Value ::as_array )
. into_iter ()
. flatten ()
. any ( | tool | {
tool . get ( "type" )
. and_then ( Value ::as_str )
. is_some_and ( | value | value . eq_ignore_ascii_case ( "image_generation" ))
&& ! tool
. get ( "action" )
. and_then ( Value ::as_str )
. is_some_and ( | value | value . eq_ignore_ascii_case ( "edit" ))
})
}
pub fn grok_is_image_edit_request ( body : & Value ) -> bool {
body . get ( "tools" )
. and_then ( Value ::as_array )
. into_iter ()
. flatten ()
. any ( | tool | {
tool . get ( "type" )
. and_then ( Value ::as_str )
. is_some_and ( | value | value . eq_ignore_ascii_case ( "image_generation" ))
&& tool
. get ( "action" )
. and_then ( Value ::as_str )
. is_some_and ( | value | value . eq_ignore_ascii_case ( "edit" ))
})
}
pub fn build_grok_image_edit_body ( body : & Value ) -> Value {
json! ({
"temporary" : true ,
"modelName" : GROK_IMAGE_EDIT_MODEL_NAME ,
"message" : extract_grok_image_prompt ( body ). unwrap_or_default (),
"enableImageGeneration" : true ,
"returnImageBytes" : false ,
"returnRawGrokInXaiRequest" : false ,
"enableImageStreaming" : true ,
"imageGenerationCount" : extract_grok_image_count ( body ). unwrap_or ( 2 ). clamp ( 1 , 2 ),
"forceConcise" : false ,
"enableSideBySide" : true ,
"sendFinalMetadata" : true ,
"isReasoning" : false ,
"disableTextFollowUps" : true ,
"responseMetadata" : {
"modelConfigOverride" : {
"modelMap" : {
"imageEditModel" : GROK_IMAGE_EDIT_MODEL_KIND ,
"imageEditModelConfig" : {
"imageReferences" : [],
"parentPostId" : ""
}
}
}
},
"disableMemory" : true ,
"forceSideBySide" : false ,
})
}
fn grok_base_app_chat_payload ( message : String , mode_id : & 'static str ) -> Map < String , Value > {
let mut payload = Map ::new ();
payload . insert ( "collectionIds" . to_string (), json! ([]));
payload . insert ( "connectors" . to_string (), json! ([]));
payload . insert (
"deviceEnvInfo" . to_string (),
json! ({
"darkModeEnabled" : false ,
"devicePixelRatio" : 2 ,
"screenHeight" : 1329 ,
"screenWidth" : 2056 ,
"viewportHeight" : 1083 ,
"viewportWidth" : 2056 ,
}),
);
payload . insert ( "disableMemory" . to_string (), json! ( true ));
payload . insert ( "disableSearch" . to_string (), json! ( false ));
payload . insert ( "disableSelfHarmShortCircuit" . to_string (), json! ( false ));
payload . insert ( "disableTextFollowUps" . to_string (), json! ( false ));
payload . insert ( "enableImageGeneration" . to_string (), json! ( true ));
payload . insert ( "enableImageStreaming" . to_string (), json! ( true ));
payload . insert ( "enableSideBySide" . to_string (), json! ( true ));
payload . insert ( "fileAttachments" . to_string (), json! ([]));
payload . insert ( "forceConcise" . to_string (), json! ( false ));
payload . insert ( "forceSideBySide" . to_string (), json! ( false ));
payload . insert ( "imageAttachments" . to_string (), json! ([]));
payload . insert ( "imageGenerationCount" . to_string (), json! ( 2 ));
payload . insert ( "isAsyncChat" . to_string (), json! ( false ));
payload . insert ( "message" . to_string (), Value ::String ( message ));
payload . insert ( "modeId" . to_string (), Value ::String ( mode_id . to_string ()));
payload . insert ( "responseMetadata" . to_string (), json! ({}));
payload . insert ( "returnImageBytes" . to_string (), json! ( false ));
payload . insert ( "returnRawGrokInXaiRequest" . to_string (), json! ( false ));
payload . insert ( "searchAllConnectors" . to_string (), json! ( false ));
payload . insert ( "sendFinalMetadata" . to_string (), json! ( true ));
payload . insert ( "temporary" . to_string (), json! ( true ));
payload . insert (
"toolOverrides" . to_string (),
json! ({
"gmailSearch" : false ,
"googleCalendarSearch" : false ,
"outlookSearch" : false ,
"outlookCalendarSearch" : false ,
"googleDriveSearch" : false ,
}),
);
payload
}
fn grok_mode_id_for_model ( model : Option <& str > ) -> & 'static str {
let model = model . unwrap_or_default (). to_ascii_lowercase ();
if model . contains ( "4.3" ) || model . contains ( "computer" ) {
"grok-420-computer-use-sa"
} else if model . contains ( "multi-agent" ) {
"heavy"
} else if model . contains ( "non-reasoning" ) || model . contains ( "fast" ) || model . contains ( "lite" ) {
"fast"
} else if model . contains ( "expert" ) || model . contains ( "reasoning" ) {
"expert"
} else if model . contains ( "0309-heavy" ) {
"auto"
} else if model . contains ( "heavy" ) {
"heavy"
} else {
"auto"
}
}
fn extract_grok_message_from_openai_chat_body ( body : & Value ) -> String {
let parts = body
. get ( "messages" )
. and_then ( Value ::as_array )
. map ( | items | {
items
. iter ()
. filter_map ( | message | {
let role = message
. get ( "role" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. unwrap_or ( "user" );
grok_chat_message_text ( message ). map ( | text | format! ( "[ {role} ]: {text} " ))
})
. collect ::< Vec < _ >> ()
})
. unwrap_or_default ();
( ! parts . is_empty ())
. then ( || parts . join ( " \n\n " ))
. or_else ( || value_text ( body . get ( "prompt" ) ? ))
. unwrap_or_default ()
}
fn extract_grok_message_from_openai_responses_body ( body : & Value ) -> String {
let mut parts = Vec ::new ();
if let Some ( instructions ) = body
. get ( "instructions" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
{
parts . push ( format! ( "system: {instructions} " ));
}
if let Some ( input ) = body . get ( "input" ). and_then ( value_text ) {
if ! input . trim (). is_empty () {
parts . push ( input );
}
}
parts . join ( " \n\n " )
}
fn extract_grok_message_from_claude_messages_body ( body : & Value ) -> String {
let mut parts = Vec ::new ();
if let Some ( system ) = body . get ( "system" ). and_then ( value_text ) {
if ! system . trim (). is_empty () {
parts . push ( format! ( "system: {system} " ));
}
}
if let Some ( messages ) = body . get ( "messages" ). and_then ( Value ::as_array ) {
for message in messages {
let role = message
. get ( "role" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. unwrap_or ( "user" );
if let Some ( text ) = grok_chat_message_text ( message ) {
parts . push ( format! ( "[ {role} ]: {text} " ));
}
}
}
parts . join ( " \n\n " )
}
fn grok_chat_message_text ( message : & Value ) -> Option < String > {
let role = message
. get ( "role" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. unwrap_or_default ();
if role . eq_ignore_ascii_case ( "tool" ) {
let text = value_text ( message . get ( "content" ) ? ) ? ;
let text = text . trim ();
if text . is_empty () {
return None ;
}
let label = message
. get ( "tool_call_id" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. map ( | id | format! ( "[tool result for {id} ]" ))
. unwrap_or_else ( || "[tool result]" . to_string ());
return Some ( format! ( " {label} : \n {text} " ));
}
if role . eq_ignore_ascii_case ( "assistant" ) {
if let Some ( tool_calls ) = message . get ( "tool_calls" ). and_then ( Value ::as_array ) {
if ! tool_calls . is_empty () {
let mut parts = Vec ::new ();
if let Some ( text ) = message . get ( "content" ). and_then ( value_text ) {
let text = text . trim ();
if ! text . is_empty () {
parts . push ( text . to_string ());
}
}
parts . push ( grok_tool_calls_text ( tool_calls ));
return Some ( parts . join ( " \n " ));
}
}
}
let text = value_text ( message . get ( "content" ) ? ) ? ;
let text = strip_grok_generated_artifacts ( text . trim ())
. trim ()
. to_string ();
( ! text . is_empty ()). then_some ( text )
}
fn grok_tool_calls_text ( tool_calls : & [ Value ]) -> String {
let mut parts = Vec ::new ();
for tool_call in tool_calls {
let function = tool_call . get ( "function" ). unwrap_or ( tool_call );
let name = function
. get ( "name" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. unwrap_or ( "tool" );
let arguments = function
. get ( "arguments" )
. and_then ( value_text )
. unwrap_or_else ( || "{}" . to_string ());
parts . push ( format! (
"<tool_call name= \" {name} \" > {arguments} </tool_call>"
));
}
parts . join ( " \n " )
}
fn strip_grok_generated_artifacts ( text : & str ) -> String {
let marker = "[grok2api-sources]: #" ;
let Some ( marker_index ) = text . find ( marker ) else {
return text . to_string ();
};
let prefix = & text [ .. marker_index ];
if let Some ( sources_index ) = prefix . rfind ( "## Sources" ) {
prefix [ .. sources_index ]. trim_end (). to_string ()
} else {
text . to_string ()
}
}
fn extract_grok_image_prompt ( body : & Value ) -> Option < String > {
body . get ( "prompt" )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. map ( ToOwned ::to_owned )
. or_else ( || body . get ( "input" ). and_then ( value_text ))
. or_else ( || extract_grok_last_user_text_from_openai_chat_body ( body ))
}
fn extract_grok_image_count ( body : & Value ) -> Option < u64 > {
body . get ( "n" )
. and_then ( Value ::as_u64 )
. or_else ( || body . get ( "imageGenerationCount" ). and_then ( Value ::as_u64 ))
. or_else ( || {
body . get ( "image_config" ). and_then ( | config | {
config
. get ( "n" )
. or_else ( || config . get ( "imageGenerationCount" ))
. and_then ( Value ::as_u64 )
})
})
. or_else ( || {
body . get ( "tools" )
. and_then ( Value ::as_array )
. into_iter ()
. flatten ()
. find_map ( | tool | {
tool . get ( "n" )
. or_else ( || tool . get ( "imageGenerationCount" ))
. and_then ( Value ::as_u64 )
})
})
}
fn extract_grok_image_option ( body : & Value , keys : & [ & str ]) -> Option < String > {
for key in keys {
if let Some ( value ) = body
. get ( * key )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
{
return Some ( value . to_string ());
}
}
if let Some ( config ) = body . get ( "image_config" ). and_then ( Value ::as_object ) {
for key in keys {
if let Some ( value ) = config
. get ( * key )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
{
return Some ( value . to_string ());
}
}
}
body . get ( "tools" )
. and_then ( Value ::as_array )
. into_iter ()
. flatten ()
. find_map ( | tool | {
keys . iter (). find_map ( | key | {
tool . get ( * key )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. map ( ToOwned ::to_owned )
})
})
}
fn extract_grok_last_user_text_from_openai_chat_body ( body : & Value ) -> Option < String > {
body . get ( "messages" )
. and_then ( Value ::as_array ) ?
. iter ()
. rev ()
. find_map ( | message | {
let role = message . get ( "role" ). and_then ( Value ::as_str ) ? ;
if ! role . eq_ignore_ascii_case ( "user" ) {
return None ;
}
grok_chat_message_text ( message )
})
}
fn value_text ( value : & Value ) -> Option < String > {
match value {
Value ::String ( text ) => Some ( text . clone ()),
Value ::Array ( items ) => {
let mut parts = Vec ::new ();
for item in items {
if let Some ( text ) = value_text ( item ) {
if ! text . trim (). is_empty () {
parts . push ( text );
}
}
}
Some ( parts . join ( " \n " ))
}
Value ::Object ( object ) => {
if is_attachment_content_block ( object ) {
return None ;
}
if let Some ( text ) = object
. get ( "text" )
. or_else ( || object . get ( "input_text" ))
. or_else ( || object . get ( "content" ))
. and_then ( value_text )
{
return Some ( text );
}
None
}
_ => None ,
}
}
fn is_attachment_content_block ( object : & Map < String , Value > ) -> bool {
let Some ( block_type ) = object . get ( "type" ). and_then ( Value ::as_str ) else {
return object . contains_key ( "image_url" )
|| object . contains_key ( "file" )
|| object . contains_key ( "file_data" )
|| object . contains_key ( "file_url" );
};
matches! (
block_type ,
"image_url" | "input_image" | "input_file" | "file" | "image" | "document"
)
}
fn parse_grok_auth_config ( transport : & GatewayProviderTransportSnapshot ) -> Option < Value > {
transport
. key
. decrypted_auth_config
. as_deref ()
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. and_then ( | value | serde_json ::from_str ::< Value > ( value ). ok ())
}
fn grok_cookie_from_transport ( transport : & GatewayProviderTransportSnapshot ) -> Option < String > {
let auth_config = parse_grok_auth_config ( transport );
let token = auth_config
. as_ref ()
. and_then ( | config | {
grok_config_string (
Some ( config ),
& [
"sso_token" ,
"ssoToken" ,
"access_token" ,
"token" ,
"session_token" ,
"sessionToken" ,
],
)
})
. or_else ( || {
let raw = transport . key . decrypted_api_key . trim ();
( ! raw . is_empty ()). then ( || raw . to_string ())
}) ? ;
let token = strip_cookie_prefix ( token . trim (), "sso=" );
if token . is_empty () {
return None ;
}
let sso_rw = auth_config
. as_ref ()
. and_then ( | config | grok_config_string ( Some ( config ), & [ "sso_rw_token" , "ssoRwToken" ]))
. map ( | value | strip_cookie_prefix ( value . trim (), "sso-rw=" ))
. filter ( | value | ! value . is_empty ())
. unwrap_or_else ( || token . clone ());
let mut parts = vec! [ format! ( "sso= {token} " ), format! ( "sso-rw= {sso_rw} " )];
if let Some ( extra_cookies ) = auth_config
. as_ref ()
. and_then ( | config | grok_config_string ( Some ( config ), & [ "cf_cookies" , "cfCookies" , "cookie" ]))
. and_then ( | value | normalize_grok_extra_cookies ( value . as_str ()))
{
parts . push ( extra_cookies );
}
if let Some ( cf_clearance ) = auth_config
. as_ref ()
. and_then ( | config | grok_config_string ( Some ( config ), & [ "cf_clearance" , "cfClearance" ]))
. map ( | value | strip_cookie_prefix ( value . trim (), "cf_clearance=" ))
. filter ( | value | ! value . is_empty ())
{
if ! parts . iter (). any ( | part | part . contains ( "cf_clearance=" )) {
parts . push ( format! ( "cf_clearance= {cf_clearance} " ));
}
}
Some ( parts . join ( "; " ))
}
fn grok_config_string ( config : Option <& Value > , fields : & [ & str ]) -> Option < String > {
grok_config_string_from_object ( config . and_then ( Value ::as_object ), fields )
}
fn grok_config_string_from_object (
object : Option <& Map < String , Value >> ,
fields : & [ & str ],
) -> Option < String > {
let object = object ? ;
fields . iter (). find_map ( | field | {
object
. get ( * field )
. and_then ( Value ::as_str )
. map ( str ::trim )
. filter ( | value | ! value . is_empty ())
. map ( ToOwned ::to_owned )
})
}
fn strip_cookie_prefix ( value : & str , prefix : & str ) -> String {
value
. strip_prefix ( prefix )
. unwrap_or ( value )
. trim ()
. to_string ()
}
fn normalize_grok_extra_cookies ( value : & str ) -> Option < String > {
let parts = value
. trim ()
. trim_matches ( ';' )
. split ( ';' )
. filter_map ( | segment | {
let ( name , value ) = segment . trim (). split_once ( '=' ) ? ;
let name = name . trim ();
let value = value . trim ();
if name . is_empty ()
|| value . is_empty ()
|| name . eq_ignore_ascii_case ( "sso" )
|| name . eq_ignore_ascii_case ( "sso-rw" )
{
return None ;
}
Some ( format! ( " {name} = {value} " ))
})
. collect ::< Vec < _ >> ();
( ! parts . is_empty ()). then ( || parts . join ( "; " ))
}
#[cfg(test)]
mod tests {
use aether_contracts ::{
ResolvedTransportProfile , TRANSPORT_BACKEND_BROWSER_WREQ , TRANSPORT_HTTP_MODE_AUTO ,
TRANSPORT_POOL_SCOPE_KEY ,
};
use serde_json ::json ;
use super ::{
build_grok_app_chat_body , build_grok_browser_headers , build_grok_upstream_url ,
grok_browser_resolved_transport_profile ,
grok_browser_resolved_transport_profile_from_auth_config , resolve_grok_session_auth ,
GrokHeaderInput , GROK_CHAT_PATH , GROK_INTERNAL_HEADER ,
};
use crate ::snapshot ::{
GatewayProviderTransportEndpoint , GatewayProviderTransportKey ,
GatewayProviderTransportProvider , GatewayProviderTransportSnapshot ,
};
fn sample_transport ( auth_config : serde_json ::Value ) -> GatewayProviderTransportSnapshot {
GatewayProviderTransportSnapshot {
provider : GatewayProviderTransportProvider {
id : "provider-1" . to_string (),
name : "Grok" . to_string (),
provider_type : "grok" . to_string (),
website : None ,
is_active : true ,
keep_priority_on_conversion : false ,
enable_format_conversion : true ,
concurrent_limit : None ,
max_retries : None ,
proxy : None ,
request_timeout_secs : None ,
stream_first_byte_timeout_secs : None ,
config : None ,
},
endpoint : GatewayProviderTransportEndpoint {
id : "endpoint-1" . to_string (),
provider_id : "provider-1" . to_string (),
api_format : "openai:chat" . to_string (),
api_family : None ,
endpoint_kind : None ,
is_active : true ,
base_url : "https://grok.com/" . to_string (),
header_rules : None ,
body_rules : None ,
max_retries : None ,
custom_path : None ,
config : None ,
format_acceptance_config : None ,
proxy : None ,
},
key : GatewayProviderTransportKey {
id : "key-1" . to_string (),
provider_id : "provider-1" . to_string (),
name : "key" . to_string (),
auth_type : "oauth" . to_string (),
is_active : true ,
api_formats : None ,
auth_type_by_format : None ,
allow_auth_channel_mismatch_formats : None ,
allowed_models : None ,
capabilities : None ,
rate_multipliers : None ,
global_priority_by_format : None ,
expires_at_unix_secs : None ,
proxy : None ,
fingerprint : None ,
2026-05-21 15:38:10 +08:00
upstream_metadata : None ,
2026-05-16 19:22:54 +08:00
decrypted_api_key : String ::new (),
decrypted_auth_config : Some ( auth_config . to_string ()),
},
}
}
#[test]
fn resolves_sso_cookie_from_auth_config () {
let transport = sample_transport ( json! ({
"sso_token" : "sso=abc" ,
"sso_rw_token" : "rw" ,
"cf_clearance" : "cf"
}));
let ( _ , value ) = resolve_grok_session_auth ( & transport ). expect ( "cookie should resolve" );
assert_eq! ( value , "sso=abc; sso-rw=rw; cf_clearance=cf" );
}
#[test]
fn resolves_sso_cookie_without_duplicate_session_cookies () {
let transport = sample_transport ( json! ({
"sso_token" : "abc" ,
"sso_rw_token" : "rw" ,
"cf_cookies" : "i18nextLng=zh; sso=ignored; sso-rw=ignored-rw; cf_clearance=cf"
}));
let ( _ , value ) = resolve_grok_session_auth ( & transport ). expect ( "cookie should resolve" );
assert_eq! ( value , "sso=abc; sso-rw=rw; i18nextLng=zh; cf_clearance=cf" );
}
#[test]
fn builds_grok_browser_headers_with_internal_marker () {
let transport = sample_transport ( json! ({ "sso_token" : "abc" }));
let transport_profile =
grok_browser_resolved_transport_profile ( None , "test" ). expect ( "profile should resolve" );
let headers = build_grok_browser_headers ( GrokHeaderInput {
transport : & transport ,
transport_profile : Some ( & transport_profile ),
request_headers : None ,
content_type : "application/json" ,
accept : "*/*" ,
header_rules : None ,
provider_request_body : & json ! ({ "message" :"hi" }),
original_request_body : & json ! ({ "messages" :[]}),
})
. expect ( "headers should build" );
assert_eq! ( headers . get ( GROK_INTERNAL_HEADER ), Some ( & "1" . to_string ()));
assert_eq! (
headers . get ( "cookie" ),
Some ( & "sso=abc; sso-rw=abc" . to_string ())
);
assert_eq! ( headers . get ( "origin" ), Some ( & "https://grok.com" . to_string ()));
assert! ( headers
. get ( "user-agent" )
. is_some_and ( | value | value . contains ( "Chrome/136.0.0.0" )));
assert_eq! (
headers . get ( "sec-ch-ua" ),
Some (
& r #""Google Chrome";v="136", "Chromium";v="136", "Not(A:Brand";v="24""# . to_string ()
)
);
assert_eq! (
headers . get ( "sec-ch-ua-platform" ),
Some ( & r #""macOS""# . to_string ())
);
}
#[test]
fn builds_grok_browser_headers_from_transport_profile () {
let mut transport = sample_transport ( json! ({
"sso_token" : "abc" ,
"user_agent" : "Mozilla/5.0 custom" ,
"browser_profile" : "chrome136"
}));
transport . key . fingerprint = Some ( json! ({
"transport_profile" : {
"profile_id" : "chrome137" ,
"backend" : "browser_wreq" ,
"extra" : { "browser_profile" : "chrome137" }
}
}));
let transport_profile = grok_browser_resolved_transport_profile ( Some ( "chrome137" ), "test" )
. expect ( "profile should resolve" );
let headers = build_grok_browser_headers ( GrokHeaderInput {
transport : & transport ,
transport_profile : Some ( & transport_profile ),
request_headers : None ,
content_type : "application/json" ,
accept : "*/*" ,
header_rules : None ,
provider_request_body : & json ! ({ "message" :"hi" }),
original_request_body : & json ! ({ "messages" :[]}),
})
. expect ( "headers should build" );
assert! ( headers
. get ( "user-agent" )
. is_some_and ( | value | value . contains ( "Chrome/137.0.0.0" )));
assert_eq! (
headers . get ( "sec-ch-ua" ),
Some (
& r #""Google Chrome";v="137", "Chromium";v="137", "Not(A:Brand";v="24""# . to_string ()
)
);
}
#[test]
fn infers_grok_browser_profile_from_legacy_user_agent () {
let auth_config = json! ({
"sso_token" : "abc" ,
"user_agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
});
let auth_config = auth_config . as_object (). expect ( "object" );
let profile = grok_browser_resolved_transport_profile_from_auth_config ( auth_config , "test" )
. expect ( "profile should resolve from user agent" );
assert_eq! ( profile . profile_id , "chrome137" );
assert_eq! (
profile
. extra
. as_ref ()
. and_then ( | value | value . get ( "browser_profile" ))
. and_then ( serde_json ::Value ::as_str ),
Some ( "chrome137" )
);
}
#[test]
fn rejects_unsupported_legacy_grok_user_agent_profile () {
let auth_config = json! ({
"sso_token" : "abc" ,
"user_agent" : "Mozilla/5.0 Version/18.0 Safari/605.1.15"
});
let auth_config = auth_config . as_object (). expect ( "object" );
assert! (
grok_browser_resolved_transport_profile_from_auth_config ( auth_config , "test" ). is_none ()
);
}
#[test]
fn rejects_unsupported_grok_browser_header_profile () {
let mut transport = sample_transport ( json! ({ "sso_token" : "abc" }));
transport . key . fingerprint = Some ( json! ({
"transport_profile" : {
"profile_id" : "safari999" ,
"backend" : "browser_wreq" ,
"extra" : { "browser_profile" : "safari999" }
}
}));
let transport_profile = ResolvedTransportProfile {
profile_id : "safari999" . to_string (),
backend : TRANSPORT_BACKEND_BROWSER_WREQ . to_string (),
http_mode : TRANSPORT_HTTP_MODE_AUTO . to_string (),
pool_scope : TRANSPORT_POOL_SCOPE_KEY . to_string (),
header_fingerprint : None ,
extra : Some ( json! ({ "browser_profile" : "safari999" })),
};
let headers = build_grok_browser_headers ( GrokHeaderInput {
transport : & transport ,
transport_profile : Some ( & transport_profile ),
request_headers : None ,
content_type : "application/json" ,
accept : "*/*" ,
header_rules : None ,
provider_request_body : & json ! ({ "message" :"hi" }),
original_request_body : & json ! ({ "messages" :[]}),
});
assert! ( headers . is_none ());
}
#[test]
fn builds_rest_chat_url_from_endpoint_base () {
let transport = sample_transport ( json! ({ "sso_token" : "abc" }));
assert_eq! (
build_grok_upstream_url ( & transport , GROK_CHAT_PATH ),
"https://grok.com/rest/app-chat/conversations/new"
);
}
#[test]
fn builds_app_chat_body_from_openai_chat_messages () {
let body = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-4.20-fast" ),
& json! ({
"messages" : [
{ "role" : "system" , "content" : "be short" },
{ "role" : "user" , "content" : [{ "type" :"text" , "text" :"hello" }]}
]
}),
);
assert_eq! ( body [ "modeId" ], "fast" );
assert_eq! ( body [ "message" ], "[system]: be short \n\n [user]: hello" );
assert_eq! ( body [ "enableImageGeneration" ], true );
}
#[test]
fn builds_app_chat_body_omits_uploaded_attachment_blocks_from_prompt () {
let body = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-4.20-fast" ),
& json! ({
"messages" : [{
"role" : "user" ,
"content" : [
{ "type" : "text" , "text" : "describe this" },
{ "type" : "image_url" , "image_url" : { "url" : "https://example.com/a.png" }},
{ "type" : "file" , "file" : { "filename" : "notes.txt" , "file_data" : "data:text/plain;base64,bm90ZXM=" }}
]
}]
}),
);
assert_eq! ( body [ "message" ], "[user]: describe this" );
}
#[test]
fn builds_app_chat_body_keeps_openai_chat_history () {
let body = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-4.20-fast" ),
& json! ({
"messages" : [
{ "role" : "system" , "content" : "remember the code word" },
{ "role" : "user" , "content" : "the code word is lantern" },
{ "role" : "assistant" , "content" : "Got it. \n\n ## Sources \n [grok2api-sources]: # \n - [old](https://example.com)" },
{ "role" : "user" , "content" : "what is the code word?" }
]
}),
);
assert_eq! (
body [ "message" ],
"[system]: remember the code word \n\n [user]: the code word is lantern \n\n [assistant]: Got it. \n\n [user]: what is the code word?"
);
}
#[test]
fn builds_app_chat_body_keeps_tool_context () {
let body = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-4.20-fast" ),
& json! ({
"messages" : [
{
"role" : "assistant" ,
"content" : null ,
"tool_calls" : [{
"id" : "call_1" ,
"type" : "function" ,
"function" : { "name" : "lookup" , "arguments" : "{ \" q \" : \" weather \" }" }
}]
},
{ "role" : "tool" , "tool_call_id" : "call_1" , "content" : "sunny" }
]
}),
);
assert! ( body [ "message" ]
. as_str ()
. expect ( "message should be string" )
. contains ( "<tool_call name= \" lookup \" >{ \" q \" : \" weather \" }</tool_call>" ));
assert! ( body [ "message" ]
. as_str ()
. expect ( "message should be string" )
. contains ( "[tool]: [tool result for call_1]: \n sunny" ));
}
#[test]
fn maps_grok_0309_model_variants_to_web_modes () {
let request = json! ({ "messages" : [{ "role" : "user" , "content" : "hello" }]});
let fast = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-4.20-0309-non-reasoning-heavy" ),
& request ,
);
let auto = build_grok_app_chat_body ( "openai:chat" , Some ( "grok-4.20-0309-heavy" ), & request );
let expert = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-4.20-0309-reasoning-super" ),
& request ,
);
let heavy =
build_grok_app_chat_body ( "openai:chat" , Some ( "grok-4.20-multi-agent-0309" ), & request );
assert_eq! ( fast [ "modeId" ], "fast" );
assert_eq! ( auto [ "modeId" ], "auto" );
assert_eq! ( expert [ "modeId" ], "expert" );
assert_eq! ( heavy [ "modeId" ], "heavy" );
}
#[test]
fn builds_app_chat_body_from_openai_image_prompt () {
let body = build_grok_app_chat_body (
"openai:image" ,
Some ( "grok-imagine-image" ),
& json! ({ "prompt" :"a red chair" , "n" : 3 }),
);
assert_eq! ( body [ "modeId" ], "auto" );
assert_eq! ( body [ "message" ], "Drawing: a red chair" );
assert_eq! ( body [ "imageGenerationCount" ], 3 );
}
#[test]
fn builds_app_chat_body_from_openai_responses_image_generation_tool () {
let body = build_grok_app_chat_body (
"openai:responses" ,
Some ( "grok-imagine-image-lite" ),
& json! ({
"input" : "a red chair" ,
"tools" : [{
"type" : "image_generation" ,
"n" : 4 ,
"size" : "1280x720"
}]
}),
);
assert_eq! ( body [ "modeId" ], "fast" );
assert_eq! ( body [ "message" ], "Drawing: a red chair" );
assert_eq! ( body [ "imageGenerationCount" ], 4 );
assert_eq! ( body [ "size" ], "1280x720" );
}
#[test]
fn app_chat_image_generation_count_uses_gateway_ceiling () {
let body = build_grok_app_chat_body (
"openai:responses" ,
Some ( "grok-imagine-image-lite" ),
& json! ({
"input" : "a red chair" ,
"tools" : [{
"type" : "image_generation" ,
"n" : 10
}]
}),
);
assert_eq! ( body [ "imageGenerationCount" ], 4 );
}
#[test]
fn builds_app_chat_body_from_openai_chat_image_model_request () {
let body = build_grok_app_chat_body (
"openai:chat" ,
Some ( "grok-imagine-image-pro" ),
& json! ({
"messages" : [
{ "role" : "system" , "content" : "ignore prior style" },
{ "role" : "user" , "content" : [{ "type" :"text" , "text" :"a blue sofa" }]}
],
"image_config" : {
"n" : 2 ,
"size" : "720x1280"
}
}),
);
assert_eq! ( body [ "message" ], "Drawing: a blue sofa" );
assert_eq! ( body [ "imageGenerationCount" ], 2 );
assert_eq! ( body [ "size" ], "720x1280" );
}
#[test]
fn builds_app_chat_body_from_openai_image_edit_request () {
let body = build_grok_app_chat_body (
"openai:image" ,
Some ( "grok-imagine-image-edit" ),
& json! ({
"input" : [
{ "type" : "input_text" , "text" : "make the chair blue" },
{ "type" : "input_image" , "image_url" : "data:image/png;base64,aW1hZ2U=" }
],
"tools" : [{
"type" : "image_generation" ,
"action" : "edit"
}]
}),
);
assert_eq! ( body [ "modelName" ], "imagine-image-edit" );
assert_eq! ( body [ "message" ], "make the chair blue" );
assert_eq! ( body [ "enableImageGeneration" ], true );
assert_eq! ( body [ "enableImageStreaming" ], true );
assert_eq! ( body [ "disableTextFollowUps" ], true );
assert_eq! ( body [ "imageGenerationCount" ], 2 );
assert_eq! (
body [ "responseMetadata" ][ "modelConfigOverride" ][ "modelMap" ][ "imageEditModel" ],
"imagine"
);
}
}