diff --git a/litellm/setup_wizard.py b/litellm/setup_wizard.py index e2a1a9c40da..38a31a25993 100644 --- a/litellm/setup_wizard.py +++ b/litellm/setup_wizard.py @@ -176,7 +176,13 @@ def _styled_input(prompt: str) -> str: def _yaml_escape(value: str) -> str: """Escape a string for safe embedding in a double-quoted YAML scalar.""" - return value.replace("\\", "\\\\").replace('"', '\\"') + return ( + value.replace("\\", "\\\\") + .replace('"', '\\"') + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t") + ) # --------------------------------------------------------------------------- diff --git a/tests/test_litellm/test_setup_wizard.py b/tests/test_litellm/test_setup_wizard.py index 21f34ce8161..e10bd893e31 100644 --- a/tests/test_litellm/test_setup_wizard.py +++ b/tests/test_litellm/test_setup_wizard.py @@ -23,6 +23,18 @@ def test_yaml_escape_combined(): assert _yaml_escape('ab\\"cd') == 'ab\\\\\\"cd' +def test_yaml_escape_newline(): + assert _yaml_escape("sk-abc\ndef") == "sk-abc\\ndef" + + +def test_yaml_escape_carriage_return(): + assert _yaml_escape("sk-abc\rdef") == "sk-abc\\rdef" + + +def test_yaml_escape_tab(): + assert _yaml_escape("sk-abc\tdef") == "sk-abc\\tdef" + + # --------------------------------------------------------------------------- # SetupWizard._build_config # --------------------------------------------------------------------------- @@ -137,7 +149,8 @@ def test_build_config_azure_no_deployment_skipped(): """Azure without a deployment name should emit nothing (not fallback to gpt-4o).""" env_vars = {"AZURE_API_KEY": "az-key"} # no deployment sentinel config = SetupWizard._build_config([_AZURE], env_vars, "sk-master") - assert "azure" not in config or "model_list:" in config # no azure model emitted + # No azure model entry should be emitted when deployment name is absent + assert "model: azure/" not in config def test_build_config_no_display_name_collision_openai_and_azure():