@@ -612,6 +612,46 @@ def test_custom_webhook_template_unescapes_compose_saved_braced_placeholders(
612612 '{"content":${content_json}}' ,
613613 )
614614
615+ @patch .object (Config , "_parse_litellm_yaml" , return_value = [])
616+ def test_custom_webhook_template_does_not_affect_llm_contract (
617+ self ,
618+ _mock_parse_litellm_yaml : object ,
619+ ) -> None :
620+ with tempfile .TemporaryDirectory () as temp_dir :
621+ env_path = Path (temp_dir ) / ".env"
622+ env_path .write_text (
623+ "\n " .join (
624+ [
625+ "STOCK_LIST=600519" ,
626+ "LITELLM_MODEL=openai/gpt-5.5" ,
627+ "OPENAI_MODEL=gpt-5.5" ,
628+ "OPENAI_API_KEY=runtime-openai-key" ,
629+ "OPENAI_BASE_URL=https://openai.example/v1" ,
630+ "CUSTOM_WEBHOOK_BODY_TEMPLATE={\" title\" :$$title_json,\" content\" :$$content_json}" ,
631+ ]
632+ )
633+ + "\n " ,
634+ encoding = "utf-8" ,
635+ )
636+
637+ with patch .dict (
638+ os .environ ,
639+ {
640+ "ENV_FILE" : str (env_path ),
641+ },
642+ clear = True ,
643+ ):
644+ config = Config ._load_from_env ()
645+
646+ self .assertEqual (config .litellm_model , "openai/gpt-5.5" )
647+ self .assertEqual (config .openai_model , "gpt-5.5" )
648+ self .assertEqual (config .openai_api_key , "runtime-openai-key" )
649+ self .assertEqual (config .openai_base_url , "https://openai.example/v1" )
650+ self .assertEqual (
651+ config .custom_webhook_body_template ,
652+ '{"title":$title_json,"content":$content_json}' ,
653+ )
654+
615655 def test_refresh_stock_list_preserves_empty_required_config (self ) -> None :
616656 with tempfile .TemporaryDirectory () as temp_dir :
617657 env_path = Path (temp_dir ) / ".env"
0 commit comments