@@ -3173,7 +3173,7 @@ async fn execute_assistant_stream(
31733173 ) ) ;
31743174 }
31753175
3176- let client = build_client ( ) ?;
3176+ let client = http :: client_assistant_stream ( ) ?;
31773177 let response = client
31783178 . post ( url)
31793179 . header ( header:: COOKIE , format ! ( "kagi_session={token}" ) )
@@ -3200,7 +3200,7 @@ async fn execute_assistant_multipart_stream(
32003200 ) ) ;
32013201 }
32023202
3203- let client = build_client ( ) ?;
3203+ let client = http :: client_assistant_stream ( ) ?;
32043204 let state_json = serde_json:: to_vec ( state) . map_err ( |error| {
32053205 KagiError :: Config ( format ! (
32063206 "failed to serialize Assistant prompt upload state: {error}"
@@ -4479,7 +4479,7 @@ mod tests {
44794479 Arc ,
44804480 atomic:: { AtomicBool , Ordering } ,
44814481 } ;
4482- use std:: time:: { SystemTime , UNIX_EPOCH } ;
4482+ use std:: time:: { Duration , SystemTime , UNIX_EPOCH } ;
44834483 use tempfile:: TempDir ;
44844484
44854485 struct ScopedEnvVar {
@@ -4920,6 +4920,19 @@ mod tests {
49204920 assert_eq ! ( parsed. message. trace_id. as_deref( ) , Some ( "trace-message-1" ) ) ;
49214921 }
49224922
4923+ #[ test]
4924+ fn parses_assistant_prompt_stream_without_expires_at ( ) {
4925+ let raw = concat ! (
4926+ "hi:{\" v\" :\" 202603091651.stage.c128588\" ,\" trace\" :\" trace-123\" }\0 \n " ,
4927+ "thread.json:{\" id\" :\" thread-1\" ,\" title\" :\" Greeting\" ,\" ack\" :\" 2026-03-16T06:19:07Z\" ,\" created_at\" :\" 2026-03-16T06:19:07Z\" ,\" saved\" :false,\" shared\" :false,\" branch_id\" :\" 00000000-0000-4000-0000-000000000000\" ,\" tag_ids\" :[]}\0 \n " ,
4928+ "new_message.json:{\" id\" :\" msg-1\" ,\" thread_id\" :\" thread-1\" ,\" created_at\" :\" 2026-03-16T06:19:07Z\" ,\" branch_list\" :[\" 00000000-0000-4000-0000-000000000000\" ],\" state\" :\" done\" ,\" prompt\" :\" Hello\" ,\" reply\" :\" <p>Hi</p>\" ,\" md\" :\" Hi\" ,\" references_html\" :\" <ol><li>Doc</li></ol>\" ,\" references_md\" :\" 1. [Doc](https://example.com)\" ,\" metadata\" :\" <li>meta</li>\" ,\" documents\" :[],\" trace_id\" :\" trace-message-1\" }\0 \n "
4929+ ) ;
4930+
4931+ let parsed = parse_assistant_prompt_stream ( raw) . expect ( "assistant stream parses" ) ;
4932+ assert_eq ! ( parsed. thread. id, "thread-1" ) ;
4933+ assert ! ( parsed. thread. expires_at. is_empty( ) ) ;
4934+ }
4935+
49234936 #[ test]
49244937 fn parses_assistant_thread_cursor_from_cursor_payload ( ) {
49254938 assert_eq ! (
@@ -5172,6 +5185,50 @@ mod tests {
51725185 assert_eq ! ( response. message. markdown. as_deref( ) , Some ( "attached-note" ) ) ;
51735186 }
51745187
5188+ #[ tokio:: test]
5189+ #[ allow( clippy:: await_holding_lock) ]
5190+ async fn assistant_prompt_accepts_delayed_stream_response ( ) {
5191+ use httpmock:: Method :: POST ;
5192+ use httpmock:: MockServer ;
5193+
5194+ let server = MockServer :: start ( ) ;
5195+ let _prompt = server. mock ( |when, then| {
5196+ when. method ( POST )
5197+ . path ( "/assistant/prompt" )
5198+ . header ( "cookie" , "kagi_session=test-session" )
5199+ . header ( "accept" , "application/vnd.kagi.stream" ) ;
5200+ then. status ( 200 )
5201+ . header ( "content-type" , "application/vnd.kagi.stream" )
5202+ . delay ( Duration :: from_millis ( 200 ) )
5203+ . body ( concat ! (
5204+ "hi:{\" v\" :\" test\" ,\" trace\" :\" trace-delayed\" }\0 \n " ,
5205+ "thread.json:{\" id\" :\" thread-delayed\" ,\" title\" :\" Delayed test\" ,\" ack\" :\" 2026-05-01T00:00:00Z\" ,\" created_at\" :\" 2026-05-01T00:00:00Z\" ,\" saved\" :false,\" shared\" :false,\" branch_id\" :\" 00000000-0000-4000-0000-000000000000\" ,\" tag_ids\" :[]}\0 \n " ,
5206+ "new_message.json:{\" id\" :\" msg-delayed\" ,\" thread_id\" :\" thread-delayed\" ,\" created_at\" :\" 2026-05-01T00:00:00Z\" ,\" state\" :\" done\" ,\" prompt\" :\" Hello\" ,\" md\" :\" delayed-ok\" ,\" documents\" :[]}\0 \n "
5207+ ) ) ;
5208+ } ) ;
5209+
5210+ let _env_guard = lock_env ( ) ;
5211+ let _base_url_env = set_env_var ( "KAGI_BASE_URL" , & server. base_url ( ) ) ;
5212+ let response = execute_assistant_prompt (
5213+ & AssistantPromptRequest {
5214+ query : "Hello" . to_string ( ) ,
5215+ thread_id : None ,
5216+ attachments : Vec :: new ( ) ,
5217+ profile_id : None ,
5218+ model : None ,
5219+ lens_id : None ,
5220+ internet_access : None ,
5221+ personalizations : None ,
5222+ } ,
5223+ "test-session" ,
5224+ )
5225+ . await
5226+ . expect ( "delayed assistant prompt should succeed" ) ;
5227+
5228+ assert_eq ! ( response. meta. trace. as_deref( ) , Some ( "trace-delayed" ) ) ;
5229+ assert_eq ! ( response. message. markdown. as_deref( ) , Some ( "delayed-ok" ) ) ;
5230+ }
5231+
51755232 #[ test]
51765233 fn normalizes_custom_bang_trigger_and_redirect_rule ( ) {
51775234 assert_eq ! (
0 commit comments