mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-02-12 17:08:14 +00:00
Compare commits
6 Commits
codex/fix-
...
alert-auto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6612753db8 | ||
|
|
46e1b02154 | ||
|
|
6712413a83 | ||
|
|
87675b49fd | ||
|
|
e9475a7215 | ||
|
|
c2d4073415 |
5
.github/codeql/codeql-config.yml
vendored
5
.github/codeql/codeql-config.yml
vendored
@@ -14,13 +14,18 @@ paths-ignore:
|
||||
- "lib/crewai/src/crewai/experimental/a2a/**"
|
||||
|
||||
paths:
|
||||
# Include GitHub Actions workflows/composite actions for CodeQL actions analysis
|
||||
- ".github/workflows/**"
|
||||
- ".github/actions/**"
|
||||
# Include all Python source code from workspace packages
|
||||
- "lib/crewai/src/**"
|
||||
- "lib/crewai-tools/src/**"
|
||||
- "lib/crewai-files/src/**"
|
||||
- "lib/devtools/src/**"
|
||||
# Include tests (but exclude cassettes via paths-ignore)
|
||||
- "lib/crewai/tests/**"
|
||||
- "lib/crewai-tools/tests/**"
|
||||
- "lib/crewai-files/tests/**"
|
||||
- "lib/devtools/tests/**"
|
||||
|
||||
# Configure specific queries or packs if needed
|
||||
|
||||
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
@@ -98,6 +98,6 @@ jobs:
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -33,8 +33,11 @@ def test_brave_tool_search(mock_get, brave_tool):
|
||||
mock_get.return_value.json.return_value = mock_response
|
||||
|
||||
result = brave_tool.run(query="test")
|
||||
assert "Test Title" in result
|
||||
assert "http://test.com" in result
|
||||
data = json.loads(result)
|
||||
assert isinstance(data, list)
|
||||
assert len(data) >= 1
|
||||
assert data[0]["title"] == "Test Title"
|
||||
assert data[0]["url"] == "http://test.com"
|
||||
|
||||
|
||||
@patch("requests.get")
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import re
|
||||
import sys
|
||||
from urllib.parse import urlparse
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
# Create mock classes that will be used by our fixture
|
||||
class MockStagehandModule:
|
||||
def __init__(self):
|
||||
@@ -171,8 +172,14 @@ def test_navigate_command(mock_run, stagehand_tool):
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert "https://example.com" in result
|
||||
assert "Successfully navigated to " in result
|
||||
|
||||
# Extract URL from result string and check its host
|
||||
# Example result: "Successfully navigated to https://example.com"
|
||||
url_match = re.search(r"https?://[^\s]+", result)
|
||||
assert url_match is not None
|
||||
parsed = urlparse(url_match.group(0))
|
||||
assert parsed.hostname == "example.com"
|
||||
|
||||
@patch(
|
||||
"crewai_tools.tools.stagehand_tool.stagehand_tool.StagehandTool._run", autospec=True
|
||||
|
||||
@@ -4,7 +4,6 @@ import json
|
||||
import logging
|
||||
import os
|
||||
from typing import TYPE_CHECKING, Any, TypedDict
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import Self
|
||||
@@ -176,51 +175,11 @@ class AzureCompletion(BaseLLM):
|
||||
prefix in model.lower() for prefix in ["gpt-", "o1-", "text-"]
|
||||
)
|
||||
|
||||
self.is_azure_openai_endpoint = self._is_azure_openai_deployment_endpoint(
|
||||
self.endpoint
|
||||
self.is_azure_openai_endpoint = (
|
||||
"openai.azure.com" in self.endpoint
|
||||
and "/openai/deployments/" in self.endpoint
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _parse_endpoint_url(endpoint: str):
|
||||
parsed_endpoint = urlparse(endpoint)
|
||||
if parsed_endpoint.hostname:
|
||||
return parsed_endpoint
|
||||
|
||||
# Support endpoint values without a URL scheme.
|
||||
return urlparse(f"https://{endpoint}")
|
||||
|
||||
@staticmethod
|
||||
def _is_azure_openai_hostname(endpoint: str) -> bool:
|
||||
parsed_endpoint = AzureCompletion._parse_endpoint_url(endpoint)
|
||||
hostname = parsed_endpoint.hostname or ""
|
||||
labels = [label for label in hostname.lower().split(".") if label]
|
||||
|
||||
return len(labels) >= 3 and labels[-3:] == ["openai", "azure", "com"]
|
||||
|
||||
@staticmethod
|
||||
def _get_endpoint_path_segments(endpoint: str) -> list[str]:
|
||||
parsed_endpoint = AzureCompletion._parse_endpoint_url(endpoint)
|
||||
return [segment for segment in parsed_endpoint.path.split("/") if segment]
|
||||
|
||||
@staticmethod
|
||||
def _is_azure_openai_deployment_endpoint(endpoint: str) -> bool:
|
||||
if not AzureCompletion._is_azure_openai_hostname(endpoint):
|
||||
return False
|
||||
|
||||
path_segments = AzureCompletion._get_endpoint_path_segments(endpoint)
|
||||
return len(path_segments) >= 3 and path_segments[:2] == [
|
||||
"openai",
|
||||
"deployments",
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def _is_azure_openai_deployments_collection(endpoint: str) -> bool:
|
||||
if not AzureCompletion._is_azure_openai_hostname(endpoint):
|
||||
return False
|
||||
|
||||
path_segments = AzureCompletion._get_endpoint_path_segments(endpoint)
|
||||
return path_segments == ["openai", "deployments"]
|
||||
|
||||
@staticmethod
|
||||
def _validate_and_fix_endpoint(endpoint: str, model: str) -> str:
|
||||
"""Validate and fix Azure endpoint URL format.
|
||||
@@ -235,12 +194,10 @@ class AzureCompletion(BaseLLM):
|
||||
Returns:
|
||||
Validated and potentially corrected endpoint URL
|
||||
"""
|
||||
if AzureCompletion._is_azure_openai_hostname(
|
||||
endpoint
|
||||
) and not AzureCompletion._is_azure_openai_deployment_endpoint(endpoint):
|
||||
if "openai.azure.com" in endpoint and "/openai/deployments/" not in endpoint:
|
||||
endpoint = endpoint.rstrip("/")
|
||||
|
||||
if not AzureCompletion._is_azure_openai_deployments_collection(endpoint):
|
||||
if not endpoint.endswith("/openai/deployments"):
|
||||
deployment_name = model.replace("azure/", "")
|
||||
endpoint = f"{endpoint}/openai/deployments/{deployment_name}"
|
||||
logging.info(f"Constructed Azure OpenAI endpoint URL: {endpoint}")
|
||||
|
||||
@@ -958,34 +958,6 @@ def test_azure_endpoint_detection_flags():
|
||||
assert llm_other.is_azure_openai_endpoint == False
|
||||
|
||||
|
||||
def test_azure_endpoint_detection_ignores_spoofed_urls():
|
||||
"""
|
||||
Test that endpoint detection does not trust spoofed host/path substrings
|
||||
"""
|
||||
with patch.dict(os.environ, {
|
||||
"AZURE_API_KEY": "test-key",
|
||||
"AZURE_ENDPOINT": (
|
||||
"https://evil.example.com/?redirect="
|
||||
"https://test.openai.azure.com/openai/deployments/gpt-4"
|
||||
),
|
||||
}):
|
||||
llm_query_spoof = LLM(model="azure/gpt-4")
|
||||
assert llm_query_spoof.is_azure_openai_endpoint == False
|
||||
assert "model" in llm_query_spoof._prepare_completion_params(
|
||||
messages=[{"role": "user", "content": "test"}]
|
||||
)
|
||||
|
||||
with patch.dict(os.environ, {
|
||||
"AZURE_API_KEY": "test-key",
|
||||
"AZURE_ENDPOINT": "https://test.openai.azure.com.evil/openai/deployments/gpt-4",
|
||||
}):
|
||||
llm_host_spoof = LLM(model="azure/gpt-4")
|
||||
assert llm_host_spoof.is_azure_openai_endpoint == False
|
||||
assert "model" in llm_host_spoof._prepare_completion_params(
|
||||
messages=[{"role": "user", "content": "test"}]
|
||||
)
|
||||
|
||||
|
||||
def test_azure_improved_error_messages():
|
||||
"""
|
||||
Test that improved error messages are provided for common HTTP errors
|
||||
|
||||
Reference in New Issue
Block a user