mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-09-19 17:46:14 +00:00
fix(tools): honor explicit empty url/token instead of the env fallback
An explicit empty string is a caller mistake, so it must reach the configuration check and be reported as missing, rather than being silently replaced by CREWAI_API_URL/CREWAI_BEARER_TOKEN. Adds a regression test and docstrings for the test functions flagged by the docstring coverage check. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -151,9 +151,17 @@ class InvokeCrewAIAutomationTool(BaseTool):
|
||||
else:
|
||||
args_schema = InvokeCrewAIAutomationInput
|
||||
|
||||
# Explicit constructor arguments win over the environment variables.
|
||||
resolved_api_url = crew_api_url or os.getenv("CREWAI_API_URL")
|
||||
resolved_bearer_token = crew_bearer_token or os.getenv("CREWAI_BEARER_TOKEN")
|
||||
# Explicit constructor arguments win over the environment variables, including
|
||||
# an explicit empty string: that is a caller mistake worth surfacing through
|
||||
# _ensure_configured(), not something to silently paper over with the environment.
|
||||
resolved_api_url = (
|
||||
crew_api_url if crew_api_url is not None else os.getenv("CREWAI_API_URL")
|
||||
)
|
||||
resolved_bearer_token = (
|
||||
crew_bearer_token
|
||||
if crew_bearer_token is not None
|
||||
else os.getenv("CREWAI_BEARER_TOKEN")
|
||||
)
|
||||
|
||||
super().__init__(
|
||||
name=crew_name or DEFAULT_TOOL_NAME,
|
||||
|
||||
@@ -59,6 +59,7 @@ def test_existing_positional_keyword_call_shape_still_works():
|
||||
|
||||
|
||||
def test_env_var_fallback_for_url_and_token():
|
||||
"""Omitted url/token are read from CREWAI_API_URL/CREWAI_BEARER_TOKEN."""
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
@@ -77,6 +78,7 @@ def test_env_var_fallback_for_url_and_token():
|
||||
|
||||
|
||||
def test_explicit_arguments_take_precedence_over_env_vars():
|
||||
"""An explicitly passed url/token wins over whatever the environment holds."""
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
@@ -130,6 +132,7 @@ def test_partial_configuration_raises_clear_error_on_use():
|
||||
@patch("requests.get")
|
||||
@patch("requests.post")
|
||||
def test_successful_run_with_env_var_configuration(mock_post, mock_get):
|
||||
"""End-to-end run (mocked HTTP) using only environment-provided credentials."""
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
@@ -164,6 +167,7 @@ def test_successful_run_with_env_var_configuration(mock_post, mock_get):
|
||||
|
||||
|
||||
def test_dynamic_crew_inputs_schema_still_works():
|
||||
"""crew_inputs keeps building a dynamic args schema for the automation inputs."""
|
||||
custom_inputs = {
|
||||
"year": Field(..., description="Year to retrieve the report for (integer)"),
|
||||
"region": Field(default="global", description="Geographic region"),
|
||||
@@ -180,3 +184,29 @@ def test_dynamic_crew_inputs_schema_still_works():
|
||||
schema_fields = tool.args_schema.model_fields
|
||||
assert "year" in schema_fields
|
||||
assert "region" in schema_fields
|
||||
|
||||
|
||||
def test_explicit_empty_value_is_not_replaced_by_env_var():
|
||||
"""An explicit empty string is a caller mistake, not a request to read the
|
||||
environment: it must reach _ensure_configured() and be reported as missing."""
|
||||
with patch.dict(
|
||||
os.environ,
|
||||
{
|
||||
"CREWAI_API_URL": "https://from-env.crewai.com",
|
||||
"CREWAI_BEARER_TOKEN": "env_token",
|
||||
},
|
||||
):
|
||||
tool = InvokeCrewAIAutomationTool(
|
||||
crew_api_url="",
|
||||
crew_name="My Crew",
|
||||
crew_description="Does things",
|
||||
)
|
||||
|
||||
assert tool.crew_api_url == ""
|
||||
assert tool.crew_bearer_token == "env_token"
|
||||
with pytest.raises(ValueError) as exc_info:
|
||||
tool.run(prompt="hello")
|
||||
|
||||
message = str(exc_info.value)
|
||||
assert "CREWAI_API_URL" in message
|
||||
assert "CREWAI_BEARER_TOKEN" not in message
|
||||
|
||||
Reference in New Issue
Block a user