chore: adjust cassette dir and regenerate openai

This commit is contained in:
Greyson LaLonde
2025-11-08 02:26:18 -05:00
parent b9bc5714c3
commit 9e75055c3e
7 changed files with 520 additions and 33 deletions

View File

@@ -1,19 +1,21 @@
# conftest.py """Pytest configuration for crewAI workspace."""
import os import os
import tempfile
from pathlib import Path from pathlib import Path
import tempfile
from typing import Any from typing import Any
import pytest import pytest
from dotenv import load_dotenv
# Load .env.test for consistent test environment (mimics CI)
env_test_path = Path(__file__).parent.parent.parent.parent / ".env.test" # Load .env.test for consistent test environment
load_dotenv(env_test_path, override=True) # env_test_path = Path(__file__).parent / ".env.test"
# load_dotenv(env_test_path, override=True)
# load_dotenv(override=True)
@pytest.fixture(autouse=True, scope="function") @pytest.fixture(autouse=True, scope="function")
def setup_test_environment(): def setup_test_environment() -> None: # type: ignore
"""Set up test environment with a temporary directory for SQLite storage.""" """Set up test environment with a temporary directory for SQLite storage."""
with tempfile.TemporaryDirectory() as temp_dir: with tempfile.TemporaryDirectory() as temp_dir:
# Create the directory with proper permissions # Create the directory with proper permissions
@@ -77,19 +79,54 @@ HEADERS_TO_FILTER = {
} }
def _filter_response_headers(response): def _filter_response_headers(response) -> dict[str, Any]: # type: ignore
"""Filter sensitive headers from response before recording.""" """Filter sensitive headers from response before recording."""
for header_name, replacement in HEADERS_TO_FILTER.items(): for header_name, replacement in HEADERS_TO_FILTER.items():
for variant in [header_name, header_name.upper(), header_name.title()]: for variant in [header_name, header_name.upper(), header_name.title()]:
if variant in response["headers"]: if variant in response["headers"]:
response["headers"][variant] = [replacement] response["headers"][variant] = [replacement]
return response return response # type: ignore
@pytest.fixture(scope="session", autouse=True) @pytest.fixture(scope="module")
def vcr_config(request) -> dict[str, Any]: def vcr_cassette_dir(request: Any) -> str:
"""Generate cassette directory path based on test module location.
Organizes cassettes to mirror test directory structure within each package:
lib/crewai/tests/llms/google/test_google.py -> lib/crewai/tests/cassettes/llms/google/
lib/crewai-tools/tests/tools/test_search.py -> lib/crewai-tools/tests/cassettes/tools/
"""
test_file = Path(request.fspath)
# Find the package root (lib/crewai or lib/crewai-tools)
for parent in test_file.parents:
if parent.name in ("crewai", "crewai-tools") and parent.parent.name == "lib":
package_root = parent
break
else:
# Fallback to old behavior if we can't find package root
package_root = test_file.parent
tests_root = package_root / "tests"
test_dir = test_file.parent
# Get relative path from tests root
if test_dir != tests_root:
relative_path = test_dir.relative_to(tests_root)
cassette_dir = tests_root / "cassettes" / relative_path
else:
cassette_dir = tests_root / "cassettes"
cassette_dir.mkdir(parents=True, exist_ok=True)
return str(cassette_dir)
@pytest.fixture(scope="module")
def vcr_config(vcr_cassette_dir: str) -> dict[str, Any]:
"""Configure VCR with organized cassette storage."""
config = { config = {
"cassette_library_dir": os.path.join(os.path.dirname(__file__), "cassettes"), "cassette_library_dir": vcr_cassette_dir,
"record_mode": os.getenv("PYTEST_VCR_RECORD_MODE") or "once", "record_mode": os.getenv("PYTEST_VCR_RECORD_MODE") or "once",
"filter_headers": [(k, v) for k, v in HEADERS_TO_FILTER.items()], "filter_headers": [(k, v) for k, v in HEADERS_TO_FILTER.items()],
"before_record_response": _filter_response_headers, "before_record_response": _filter_response_headers,

View File

@@ -1,18 +1,9 @@
"""Test A2A wrapper is only applied when a2a is passed to Agent.""" """Test A2A wrapper is only applied when a2a is passed to Agent."""
from unittest.mock import patch
import pytest
from crewai import Agent from crewai import Agent
from crewai.a2a.config import A2AConfig from crewai.a2a.config import A2AConfig
try: import a2a # noqa: F401
import a2a # noqa: F401
A2A_SDK_INSTALLED = True
except ImportError:
A2A_SDK_INSTALLED = False
def test_agent_without_a2a_has_no_wrapper(): def test_agent_without_a2a_has_no_wrapper():
@@ -27,10 +18,6 @@ def test_agent_without_a2a_has_no_wrapper():
assert callable(agent.execute_task) assert callable(agent.execute_task)
@pytest.mark.skipif(
True,
reason="Requires a2a-sdk to be installed. This test verifies wrapper is applied when a2a is set.",
)
def test_agent_with_a2a_has_wrapper(): def test_agent_with_a2a_has_wrapper():
"""Verify that agents with a2a get the wrapper applied.""" """Verify that agents with a2a get the wrapper applied."""
a2a_config = A2AConfig( a2a_config = A2AConfig(
@@ -49,7 +36,6 @@ def test_agent_with_a2a_has_wrapper():
assert callable(agent.execute_task) assert callable(agent.execute_task)
@pytest.mark.skipif(not A2A_SDK_INSTALLED, reason="Requires a2a-sdk to be installed")
def test_agent_with_a2a_creates_successfully(): def test_agent_with_a2a_creates_successfully():
"""Verify that creating an agent with a2a succeeds and applies wrapper.""" """Verify that creating an agent with a2a succeeds and applies wrapper."""
a2a_config = A2AConfig( a2a_config = A2AConfig(
@@ -89,7 +75,6 @@ def test_multiple_agents_without_a2a():
assert callable(agent2.execute_task) assert callable(agent2.execute_task)
@pytest.mark.skipif(not A2A_SDK_INSTALLED, reason="Requires a2a-sdk to be installed")
def test_wrapper_is_applied_differently_per_instance(): def test_wrapper_is_applied_differently_per_instance():
"""Verify that agents with and without a2a have different execute_task methods.""" """Verify that agents with and without a2a have different execute_task methods."""
agent_without_a2a = Agent( agent_without_a2a = Agent(

View File

@@ -0,0 +1,335 @@
interactions:
- request:
body: '{"trace_id": "e9702504-ee01-4414-a97d-4a31b21ea508", "execution_type":
"crew", "user_identifier": null, "execution_context": {"crew_fingerprint": null,
"crew_name": "crew", "flow_name": null, "crewai_version": "1.4.1", "privacy_level":
"standard"}, "execution_metadata": {"expected_duration_estimate": 300, "agent_count":
0, "task_count": 0, "flow_method_count": 0, "execution_started_at": "2025-11-08T07:11:54.711549+00:00"},
"ephemeral_trace_id": "e9702504-ee01-4414-a97d-4a31b21ea508"}'
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate, zstd
Connection:
- keep-alive
Content-Length:
- '488'
Content-Type:
- application/json
User-Agent:
- CrewAI-CLI/1.4.1
X-Crewai-Organization-Id:
- 73c2b193-f579-422c-84c7-76a39a1da77f
X-Crewai-Version:
- 1.4.1
authorization:
- AUTHORIZATION-XXX
method: POST
uri: https://app.crewai.com/crewai_plus/api/v1/tracing/ephemeral/batches
response:
body:
string: '{"id":"e03b258c-9817-48ed-bfb0-0fb904658f86","ephemeral_trace_id":"e9702504-ee01-4414-a97d-4a31b21ea508","execution_type":"crew","crew_name":"crew","flow_name":null,"status":"running","duration_ms":null,"crewai_version":"1.4.1","total_events":0,"execution_context":{"crew_fingerprint":null,"crew_name":"crew","flow_name":null,"crewai_version":"1.4.1","privacy_level":"standard"},"created_at":"2025-11-08T07:11:55.047Z","updated_at":"2025-11-08T07:11:55.047Z","access_code":"TRACE-3c6490d729","user_identifier":null}'
headers:
Connection:
- keep-alive
Content-Length:
- '515'
Content-Type:
- application/json; charset=utf-8
Date:
- Sat, 08 Nov 2025 07:11:55 GMT
cache-control:
- no-store
content-security-policy:
- CSP-FILTERED
etag:
- ETAG-XXX
expires:
- '0'
permissions-policy:
- PERMISSIONS-POLICY-XXX
pragma:
- no-cache
referrer-policy:
- REFERRER-POLICY-XXX
strict-transport-security:
- STS-XXX
vary:
- Accept
x-content-type-options:
- X-CONTENT-TYPE-XXX
x-frame-options:
- X-FRAME-OPTIONS-XXX
x-permitted-cross-domain-policies:
- X-PERMITTED-XXX
x-request-id:
- X-REQUEST-ID-XXX
x-runtime:
- X-RUNTIME-XXX
x-xss-protection:
- X-XSS-PROTECTION-XXX
status:
code: 201
message: Created
- request:
body: !!binary |
CuctCiQKIgoMc2VydmljZS5uYW1lEhIKEGNyZXdBSS10ZWxlbWV0cnkSvi0KEgoQY3Jld2FpLnRl
bGVtZXRyeRKXCAoQ5OwTi+Kgn9LxY8G/8cbfzRIIbhlHSeX/ZToqDENyZXcgQ3JlYXRlZDABOVhB
A+iM9nUYQXA2GeiM9nUYShkKDmNyZXdhaV92ZXJzaW9uEgcKBTEuNC4xShsKDnB5dGhvbl92ZXJz
aW9uEgkKBzMuMTIuMTBKLgoIY3Jld19rZXkSIgogZDg5OGE0ZTcyZWE2OGU2NTJhMzNjNjRlOTNl
Y2M5OWNKMQoHY3Jld19pZBImCiRmYjMxMGU2YS05MTcwLTQzNmUtODU4OC00OGQ0NTljZDQ1NjJK
OgoQY3Jld19maW5nZXJwcmludBImCiQ3NjRjZTZjYi0zMmQxLTRhYmQtYWVmOC00M2YxODU3ZDkw
NDRKHAoMY3Jld19wcm9jZXNzEgwKCnNlcXVlbnRpYWxKEQoLY3Jld19tZW1vcnkSAhAAShoKFGNy
ZXdfbnVtYmVyX29mX3Rhc2tzEgIYAUobChVjcmV3X251bWJlcl9vZl9hZ2VudHMSAhgBSjsKG2Ny
ZXdfZmluZ2VycHJpbnRfY3JlYXRlZF9hdBIcChoyMDI1LTExLTA4VDAyOjExOjU0LjIzMDA0N0rM
AgoLY3Jld19hZ2VudHMSvAIKuQJbeyJrZXkiOiAiNGEyNWIwMDEyYWU0M2M5MGRkNWNmZDMxMTA5
OGY3OTUiLCAiaWQiOiAiN2QyMzMwMTEtNDVhOC00MGIwLTk5NWYtNGUyNmYyZjVlY2I1IiwgInJv
bGUiOiAiVGVzdCBBZ2VudCIsICJ2ZXJib3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1h
eF9ycG0iOiBudWxsLCAiZnVuY3Rpb25fY2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8i
LCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/Ijog
ZmFsc2UsICJtYXhfcmV0cnlfbGltaXQiOiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSv8BCgpjcmV3
X3Rhc2tzEvABCu0BW3sia2V5IjogImIyNGYyNWQzODhhNGE0MWY5N2IwMzY2NTYyOGQyMzRlIiwg
ImlkIjogIjI5N2JkYTc4LWMxYzktNDRmOS1iMTA0LWM3ZGRhYzkwMmRlOSIsICJhc3luY19leGVj
dXRpb24/IjogZmFsc2UsICJodW1hbl9pbnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiVGVz
dCBBZ2VudCIsICJhZ2VudF9rZXkiOiAiNGEyNWIwMDEyYWU0M2M5MGRkNWNmZDMxMTA5OGY3OTUi
LCAidG9vbHNfbmFtZXMiOiBbXX1degIYAYUBAAEAABKcBAoQiNvSWaQbLRbGpp/kBq4pHxII3acE
dlrt1OwqDFRhc2sgQ3JlYXRlZDABOYgkReiM9nUYQQhXR+iM9nUYSi4KCGNyZXdfa2V5EiIKIGQ4
OThhNGU3MmVhNjhlNjUyYTMzYzY0ZTkzZWNjOTljSjEKB2NyZXdfaWQSJgokZmIzMTBlNmEtOTE3
MC00MzZlLTg1ODgtNDhkNDU5Y2Q0NTYySjoKEGNyZXdfZmluZ2VycHJpbnQSJgokNzY0Y2U2Y2It
MzJkMS00YWJkLWFlZjgtNDNmMTg1N2Q5MDQ0Si4KCHRhc2tfa2V5EiIKIGIyNGYyNWQzODhhNGE0
MWY5N2IwMzY2NTYyOGQyMzRlSjEKB3Rhc2tfaWQSJgokMjk3YmRhNzgtYzFjOS00NGY5LWIxMDQt
YzdkZGFjOTAyZGU5SjoKEHRhc2tfZmluZ2VycHJpbnQSJgokMWNlNTY0N2YtNTVkZS00YzQwLWE5
NGQtOTZmZGRjMjYzOWZjSjsKG3Rhc2tfZmluZ2VycHJpbnRfY3JlYXRlZF9hdBIcChoyMDI1LTEx
LTA4VDAyOjExOjU0LjIyOTgxOEo7ChFhZ2VudF9maW5nZXJwcmludBImCiQ1MmFkZmU2Yy0xZGIy
LTQ0MjYtYmMxNS1lMWExNDFlMWNmOGVKGgoKYWdlbnRfcm9sZRIMCgpUZXN0IEFnZW50egIYAYUB
AAEAABLhAwoQA0G2MzGBgIAlMTYgJWRMxhIIpYnGpKGS0TAqDlRhc2sgRXhlY3V0aW9uMAE5GPtH
6Iz2dRhBQPCi6Iz2dRhKLgoIY3Jld19rZXkSIgogZDg5OGE0ZTcyZWE2OGU2NTJhMzNjNjRlOTNl
Y2M5OWNKMQoHY3Jld19pZBImCiRmYjMxMGU2YS05MTcwLTQzNmUtODU4OC00OGQ0NTljZDQ1NjJK
OgoQY3Jld19maW5nZXJwcmludBImCiQ3NjRjZTZjYi0zMmQxLTRhYmQtYWVmOC00M2YxODU3ZDkw
NDRKLgoIdGFza19rZXkSIgogYjI0ZjI1ZDM4OGE0YTQxZjk3YjAzNjY1NjI4ZDIzNGVKMQoHdGFz
a19pZBImCiQyOTdiZGE3OC1jMWM5LTQ0ZjktYjEwNC1jN2RkYWM5MDJkZTlKOwoRYWdlbnRfZmlu
Z2VycHJpbnQSJgokNTJhZGZlNmMtMWRiMi00NDI2LWJjMTUtZTFhMTQxZTFjZjhlShoKCmFnZW50
X3JvbGUSDAoKVGVzdCBBZ2VudEo6ChB0YXNrX2ZpbmdlcnByaW50EiYKJDFjZTU2NDdmLTU1ZGUt
NGM0MC1hOTRkLTk2ZmRkYzI2MzlmY3oCGAGFAQABAAASpwgKEBoj6ZRqMncKbcghjbnAWUcSCPB6
e/eWFevXKgxDcmV3IENyZWF0ZWQwATlotlvsjPZ1GEGIYnbsjPZ1GEoZCg5jcmV3YWlfdmVyc2lv
bhIHCgUxLjQuMUobCg5weXRob25fdmVyc2lvbhIJCgczLjEyLjEwSi4KCGNyZXdfa2V5EiIKIDdh
OTk2YjBmMjM1ZTNjNWVkZTI5MjAxOGM4OTViMjBlSjEKB2NyZXdfaWQSJgokODE4MGRlYjAtN2Ez
NC00YjdmLThlYTEtZmNmNzVlMzg2MmU3SjoKEGNyZXdfZmluZ2VycHJpbnQSJgokYmVkYzY1ODgt
NzRiZi00MDc1LThjMGEtZGIyYTQ5M2Q4YmRkShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFs
ShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19u
dW1iZXJfb2ZfYWdlbnRzEgIYAUo7ChtjcmV3X2ZpbmdlcnByaW50X2NyZWF0ZWRfYXQSHAoaMjAy
NS0xMS0wOFQwMjoxMTo1NC4zMDUzMTRK1AIKC2NyZXdfYWdlbnRzEsQCCsECW3sia2V5IjogIjIw
YjQ2ZjFhMDM3ZjE3MmZjZWZkMmNiMDMwMmNjZjgzIiwgImlkIjogIjE1MzYyNjhlLWJjYmYtNDVk
ZC04OTk5LWQ0N2IzYmYxOTg2ZiIsICJyb2xlIjogIlJlc2VhcmNoIEFzc2lzdGFudCIsICJ2ZXJi
b3NlPyI6IGZhbHNlLCAibWF4X2l0ZXIiOiAyNSwgIm1heF9ycG0iOiBudWxsLCAiZnVuY3Rpb25f
Y2FsbGluZ19sbG0iOiAiIiwgImxsbSI6ICJncHQtNG8iLCAiZGVsZWdhdGlvbl9lbmFibGVkPyI6
IGZhbHNlLCAiYWxsb3dfY29kZV9leGVjdXRpb24/IjogZmFsc2UsICJtYXhfcmV0cnlfbGltaXQi
OiAyLCAidG9vbHNfbmFtZXMiOiBbXX1dSocCCgpjcmV3X3Rhc2tzEvgBCvUBW3sia2V5IjogIjYx
MmRjNjlhMjEwOWFhYzkwZWY3MTFjOTExYTFlZjZkIiwgImlkIjogImZkY2IxMGE3LTRiMDUtNDVj
MS04YjQzLTM2MTM2M2ZhNWU0MSIsICJhc3luY19leGVjdXRpb24/IjogZmFsc2UsICJodW1hbl9p
bnB1dD8iOiBmYWxzZSwgImFnZW50X3JvbGUiOiAiUmVzZWFyY2ggQXNzaXN0YW50IiwgImFnZW50
X2tleSI6ICIyMGI0NmYxYTAzN2YxNzJmY2VmZDJjYjAzMDJjY2Y4MyIsICJ0b29sc19uYW1lcyI6
IFtdfV16AhgBhQEAAQAAEqQEChDE5eZ8gyOi+JWLOqBc8BN7Egifc/dK/JRbMCoMVGFzayBDcmVh
dGVkMAE5wMib7Iz2dRhB2Lid7Iz2dRhKLgoIY3Jld19rZXkSIgogN2E5OTZiMGYyMzVlM2M1ZWRl
MjkyMDE4Yzg5NWIyMGVKMQoHY3Jld19pZBImCiQ4MTgwZGViMC03YTM0LTRiN2YtOGVhMS1mY2Y3
NWUzODYyZTdKOgoQY3Jld19maW5nZXJwcmludBImCiRiZWRjNjU4OC03NGJmLTQwNzUtOGMwYS1k
YjJhNDkzZDhiZGRKLgoIdGFza19rZXkSIgogNjEyZGM2OWEyMTA5YWFjOTBlZjcxMWM5MTFhMWVm
NmRKMQoHdGFza19pZBImCiRmZGNiMTBhNy00YjA1LTQ1YzEtOGI0My0zNjEzNjNmYTVlNDFKOgoQ
dGFza19maW5nZXJwcmludBImCiQzYTVhY2RiZi0yOTQxLTQ2ZTItODlhMC1hNzQ2YTcyM2QyNmFK
OwobdGFza19maW5nZXJwcmludF9jcmVhdGVkX2F0EhwKGjIwMjUtMTEtMDhUMDI6MTE6NTQuMzA1
MjczSjsKEWFnZW50X2ZpbmdlcnByaW50EiYKJDg2Yzg2NTAwLWI5ODEtNDIzMC04ZGE4LTA3MzE5
MDk4Njc5NUoiCgphZ2VudF9yb2xlEhQKElJlc2VhcmNoIEFzc2lzdGFudHoCGAGFAQABAAAS6QMK
EIGjazYO3GmE6OQW3Ik4NNcSCHormvhvVOoQKg5UYXNrIEV4ZWN1dGlvbjABOaBonuyM9nUYQUBr
teyM9nUYSi4KCGNyZXdfa2V5EiIKIDdhOTk2YjBmMjM1ZTNjNWVkZTI5MjAxOGM4OTViMjBlSjEK
B2NyZXdfaWQSJgokODE4MGRlYjAtN2EzNC00YjdmLThlYTEtZmNmNzVlMzg2MmU3SjoKEGNyZXdf
ZmluZ2VycHJpbnQSJgokYmVkYzY1ODgtNzRiZi00MDc1LThjMGEtZGIyYTQ5M2Q4YmRkSi4KCHRh
c2tfa2V5EiIKIDYxMmRjNjlhMjEwOWFhYzkwZWY3MTFjOTExYTFlZjZkSjEKB3Rhc2tfaWQSJgok
ZmRjYjEwYTctNGIwNS00NWMxLThiNDMtMzYxMzYzZmE1ZTQxSjsKEWFnZW50X2ZpbmdlcnByaW50
EiYKJDg2Yzg2NTAwLWI5ODEtNDIzMC04ZGE4LTA3MzE5MDk4Njc5NUoiCgphZ2VudF9yb2xlEhQK
ElJlc2VhcmNoIEFzc2lzdGFudEo6ChB0YXNrX2ZpbmdlcnByaW50EiYKJDNhNWFjZGJmLTI5NDEt
NDZlMi04OWEwLWE3NDZhNzIzZDI2YXoCGAGFAQABAAASpggKEFLXUh5Z1WIsgOQ3KtCkrs4SCLNn
HEHKdDaoKgxDcmV3IENyZWF0ZWQwATlwQ0PyjPZ1GEE4tmLyjPZ1GEoZCg5jcmV3YWlfdmVyc2lv
bhIHCgUxLjQuMUobCg5weXRob25fdmVyc2lvbhIJCgczLjEyLjEwSi4KCGNyZXdfa2V5EiIKIGYy
MjdkMTEyMjI3MjU2OWNhYzIxNzdmZWM2NTVkNGY5SjEKB2NyZXdfaWQSJgokYmExMTgyZGUtNmJi
Ni00ZGI3LWEwZWUtYjNhY2FlNjcxMWNjSjoKEGNyZXdfZmluZ2VycHJpbnQSJgokY2U3OTBjYTIt
YTEyZi00MzljLTlkMWMtMmFmN2FhODA5ZWZmShwKDGNyZXdfcHJvY2VzcxIMCgpzZXF1ZW50aWFs
ShEKC2NyZXdfbWVtb3J5EgIQAEoaChRjcmV3X251bWJlcl9vZl90YXNrcxICGAFKGwoVY3Jld19u
dW1iZXJfb2ZfYWdlbnRzEgIYAUo7ChtjcmV3X2ZpbmdlcnByaW50X2NyZWF0ZWRfYXQSHAoaMjAy
NS0xMS0wOFQwMjoxMTo1NC40MDQxMzFK0wIKC2NyZXdfYWdlbnRzEsMCCsACW3sia2V5IjogIjAw
ODM5OTZmNDBiOGMzNGU5NThkOGQzY2QxYWRhOTc0IiwgImlkIjogIjRmMmQxZDg4LTIyYmItNDNj
YS04YjEzLTVkODZiZmJhMjNiYyIsICJyb2xlIjogIlJlc2VhcmNoIEFzc2lzdGFudCIsICJ2ZXJi
b3NlPyI6IHRydWUsICJtYXhfaXRlciI6IDI1LCAibWF4X3JwbSI6IG51bGwsICJmdW5jdGlvbl9j
YWxsaW5nX2xsbSI6ICIiLCAibGxtIjogImdwdC00byIsICJkZWxlZ2F0aW9uX2VuYWJsZWQ/Ijog
ZmFsc2UsICJhbGxvd19jb2RlX2V4ZWN1dGlvbj8iOiBmYWxzZSwgIm1heF9yZXRyeV9saW1pdCI6
IDIsICJ0b29sc19uYW1lcyI6IFtdfV1KhwIKCmNyZXdfdGFza3MS+AEK9QFbeyJrZXkiOiAiMmVh
MzQ5ZTllMmQ1ZmZiNThjN2FjZGRhMGEzNzNjYTkiLCAiaWQiOiAiMzBjOGQ3MzktNDNiOS00NzI4
LTg2ZDItZDgwMDY5Zjk3MWQ0IiwgImFzeW5jX2V4ZWN1dGlvbj8iOiBmYWxzZSwgImh1bWFuX2lu
cHV0PyI6IGZhbHNlLCAiYWdlbnRfcm9sZSI6ICJSZXNlYXJjaCBBc3Npc3RhbnQiLCAiYWdlbnRf
a2V5IjogIjAwODM5OTZmNDBiOGMzNGU5NThkOGQzY2QxYWRhOTc0IiwgInRvb2xzX25hbWVzIjog
W119XXoCGAGFAQABAAASpAQKEHwnB3P/jEz2b/dR7U+PphMSCFj487heRbtfKgxUYXNrIENyZWF0
ZWQwATkIkajyjPZ1GEEgh6nyjPZ1GEouCghjcmV3X2tleRIiCiBmMjI3ZDExMjIyNzI1NjljYWMy
MTc3ZmVjNjU1ZDRmOUoxCgdjcmV3X2lkEiYKJGJhMTE4MmRlLTZiYjYtNGRiNy1hMGVlLWIzYWNh
ZTY3MTFjY0o6ChBjcmV3X2ZpbmdlcnByaW50EiYKJGNlNzkwY2EyLWExMmYtNDM5Yy05ZDFjLTJh
ZjdhYTgwOWVmZkouCgh0YXNrX2tleRIiCiAyZWEzNDllOWUyZDVmZmI1OGM3YWNkZGEwYTM3M2Nh
OUoxCgd0YXNrX2lkEiYKJDMwYzhkNzM5LTQzYjktNDcyOC04NmQyLWQ4MDA2OWY5NzFkNEo6ChB0
YXNrX2ZpbmdlcnByaW50EiYKJDIzMjBlNGYzLTE3ZTItNGIyNS05MjI1LTlkYTE4ZDBlMTIyN0o7
Cht0YXNrX2ZpbmdlcnByaW50X2NyZWF0ZWRfYXQSHAoaMjAyNS0xMS0wOFQwMjoxMTo1NC40MDQw
ODlKOwoRYWdlbnRfZmluZ2VycHJpbnQSJgokZmY3YzBlODktOWY3NC00NTMwLTljZDktMzNkMjg0
NDdmODg4SiIKCmFnZW50X3JvbGUSFAoSUmVzZWFyY2ggQXNzaXN0YW50egIYAYUBAAEAAA==
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate, zstd
Connection:
- keep-alive
Content-Length:
- '5866'
Content-Type:
- application/x-protobuf
User-Agent:
- OTel-OTLP-Exporter-Python/1.38.0
method: POST
uri: https://telemetry.crewai.com:4319/v1/traces
response:
body:
string: "\n\0"
headers:
Content-Length:
- '2'
Content-Type:
- application/x-protobuf
Date:
- Sat, 08 Nov 2025 07:11:55 GMT
status:
code: 200
message: OK
- request:
body: '{"messages":[{"role":"system","content":"You are Research Assistant. You
are a helpful research assistant.\nYour personal goal is: Find information about
the population of Tokyo\nTo give my best complete final answer to the task respond
using the exact following format:\n\nThought: I now can give a great answer\nFinal
Answer: Your final answer must be the great and the most complete as possible,
it must be outcome described.\n\nI MUST use these formats, my job depends on
it!"},{"role":"user","content":"\nCurrent Task: Find information about the population
of Tokyo\n\nThis is the expected criteria for your final answer: The population
of Tokyo is 10 million\nyou MUST return the actual complete content as the final
answer, not a summary.\n\nBegin! This is VERY important to you, use the tools
available and give your best Final Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4o"}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate, zstd
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '900'
content-type:
- application/json
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.109.1
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.109.1
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAA4xUTW/jRgy9+1cQuuxFNmzH+fItLdBiixYoggD92F0Y9IiSuB4N1SEVb7DIfy9m
ZMdOdgv0YsB8fE/vcYbzdQJQcFWsoXAtmut6P/3x7z9/X1jDzQ/bq/v36Jpf/7nf3d9H/aXiv4oy
MWT7mZwdWTMnXe/JWMIIu0holFQX11fLy5vL28VlBjqpyCda09t0JdPlfLmazm+m86sDsRV2pMUa
PkwAAL7m32QxVPSlWMO8PFY6UsWGivVLE0ARxadKgaqshsGK8gQ6CUYhu35oZWhaW8N7CLIHhwEa
fiRAaJJ1wKB7igAfw08c0MNd/r+Gh5agl37wmMKC1PAguycpYd+ya4EVJFAqW0uwl+irdwqdqI0s
GRQcG5OWQF8cUaWwmEPH3ie5nqT3NIM7PUp4NFIDfET2uPUEFRqWGfo5zziOBuAuEh5dUEjngaqk
B/Q3sii9eFbAUAGbgg4xyhAqDg30kWpyNsTkq0UFfBNSHinCxfUboyV0uEt8tuzodc7u+E3DABgJ
gcNpLDP4g609VL4xyabk65wzUiKPDhYXLw4iKVcUTGfw0LKe+41Ue3J2yP5OQQ1tUMi5OvwsERov
W/TpKJ5K2AXZB6gl5rmQkyAdO+BQ+4GCoxLc4G2I6EG5CVyzw1xOo8yi7bAd+cEohuwCPdQcUl9u
c9J1FB3Nzu9jpHpQTOsQBu/PAAxBLMvkTfh0QJ5f7r6Xpo+y1TfUoubA2m4ioUpI91xN+iKjzxOA
T3nHhldrU/RRut42JjvKn1tcX4x6xWmrz9Dl6oCaGPoTsLy9Lr8juKnIkL2erWnh0LVUnainncah
YjkDJmexv7XzPe0xOofm/8ifAOeoN6o2faSK3evIp7ZI6dX7r7aXMWfDhVJ8ZEcbY4rpKCqqcfDj
g1Tokxp1m5pDQ7GPPL5Kdb/ZLlar5fJ2gTfF5HnyLwAAAP//AwDuELD3ngUAAA==
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Sat, 08 Nov 2025 07:11:57 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '2312'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '2336'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-project-requests:
- '10000'
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-project-requests:
- '9999'
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-project-requests:
- 6ms
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,129 @@
interactions:
- request:
body: '{"messages":[{"role":"system","content":"You are Research Assistant. You
are a helpful research assistant.\nYour personal goal is: Find information about
the population of Tokyo\nTo give my best complete final answer to the task respond
using the exact following format:\n\nThought: I now can give a great answer\nFinal
Answer: Your final answer must be the great and the most complete as possible,
it must be outcome described.\n\nI MUST use these formats, my job depends on
it!"},{"role":"user","content":"\nCurrent Task: Find information about the population
of Tokyo\n\nThis is the expected criteria for your final answer: The population
of Tokyo is 10 million\nyou MUST return the actual complete content as the final
answer, not a summary.\n\nBegin! This is VERY important to you, use the tools
available and give your best Final Answer, your job depends on it!\n\nThought:"}],"model":"gpt-4.1-mini"}'
headers:
accept:
- application/json
accept-encoding:
- gzip, deflate, zstd
authorization:
- AUTHORIZATION-XXX
connection:
- keep-alive
content-length:
- '906'
content-type:
- application/json
host:
- api.openai.com
user-agent:
- OpenAI/Python 1.109.1
x-stainless-arch:
- X-STAINLESS-ARCH-XXX
x-stainless-async:
- 'false'
x-stainless-lang:
- python
x-stainless-os:
- X-STAINLESS-OS-XXX
x-stainless-package-version:
- 1.109.1
x-stainless-read-timeout:
- X-STAINLESS-READ-TIMEOUT-XXX
x-stainless-retry-count:
- '0'
x-stainless-runtime:
- CPython
x-stainless-runtime-version:
- 3.12.10
method: POST
uri: https://api.openai.com/v1/chat/completions
response:
body:
string: !!binary |
H4sIAAAAAAAAAwAAAP//jFRRj9NIDH7vr7Dm5V7SatNt2dI3dAcCJBASi+4Ehyp34iSGyXg042y3
oP3vaJLdpnCLdC+RZj5/tr8v9nyfARiuzBaMbVFtF9z8z4//vLtcr/5eH76Vr6tXz68Thvert7fN
Xx+ePTVFZsj+C1l9YC2sdMGRsvgRtpFQKWctr54s15v10/JqADqpyGVaE3S+WpTzjj3PlxfL9fxi
NS9X9/RW2FIyW/g0AwD4Pnxzo76iW7OFi+LhpqOUsCGzPQUBmCgu3xhMiZOiV1NMoBWv5Ifer1vp
m1a38Aq8HMCih4ZvCBCaLADQpwPFf/0L9ujg2XDawnVLECT0DrNgkBqu5etRgBNgCFFuuUMld4Ry
BR07l4PYg7YEy0tIgSyjgwPGKgFGwgIOLds286VW8mDFJ64oUjWQrESaqljW4wJeyoFuKBbANRyl
P1EGAnnlSPfxb0ijBHGcTnW8dX1F6dGOilyAKRWgcvCpAPQV3LBz2FB6kHGgpBQ9BIyaO8t3IVJN
VvtIxXieHMrG7KXXc0NUoFyfToEkOFoM1tbc9KPg8mLyL0GSjpQ7SrlDqqCWUa0lrxHdYMwf6bzu
vleohBJ4USCfhxTTKHsfBbNd3YM7iv7Xn5G48VyzRa/uCA5jQ3FxPkmR6j5hHmffO3cGoPeiQw/D
DH++R+5OU+ukCVH26ReqqdlzaneRMInPE5pUghnQuxnA52E7+p8G3oQoXdCdylcaypVXl2M+M23l
GVqu71EVRTcBy82meCThriJFdulswYxF21I1UadtxL5iOQNmZ7L/285juUfp7Jv/k34CrKWgVO1C
pIrtz5KnsEj51fpd2MnmoWGTKN6wpZ0yxfwrKqqxd+NTYtIxKXW7mn1DMUQe35M67FZ2uVmX9ebJ
0szuZj8AAAD//wMA850i/F4FAAA=
headers:
CF-RAY:
- CF-RAY-XXX
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Sat, 08 Nov 2025 07:11:59 GMT
Server:
- cloudflare
Set-Cookie:
- SET-COOKIE-XXX
Strict-Transport-Security:
- STS-XXX
Transfer-Encoding:
- chunked
X-Content-Type-Options:
- X-CONTENT-TYPE-XXX
access-control-expose-headers:
- ACCESS-CONTROL-XXX
alt-svc:
- h3=":443"; ma=86400
cf-cache-status:
- DYNAMIC
openai-organization:
- OPENAI-ORG-XXX
openai-processing-ms:
- '1472'
openai-project:
- OPENAI-PROJECT-XXX
openai-version:
- '2020-10-01'
x-envoy-upstream-service-time:
- '1532'
x-openai-proxy-wasm:
- v0.1
x-ratelimit-limit-project-tokens:
- '150000000'
x-ratelimit-limit-requests:
- X-RATELIMIT-LIMIT-REQUESTS-XXX
x-ratelimit-limit-tokens:
- X-RATELIMIT-LIMIT-TOKENS-XXX
x-ratelimit-remaining-project-tokens:
- '149999800'
x-ratelimit-remaining-requests:
- X-RATELIMIT-REMAINING-REQUESTS-XXX
x-ratelimit-remaining-tokens:
- X-RATELIMIT-REMAINING-TOKENS-XXX
x-ratelimit-reset-project-tokens:
- 0s
x-ratelimit-reset-requests:
- X-RATELIMIT-RESET-REQUESTS-XXX
x-ratelimit-reset-tokens:
- X-RATELIMIT-RESET-TOKENS-XXX
x-request-id:
- X-REQUEST-ID-XXX
status:
code: 200
message: OK
version: 1

View File

@@ -324,9 +324,9 @@ def test_openai_completion_call_returns_usage_metrics():
crew = Crew(agents=[agent], tasks=[task]) crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff() result = crew.kickoff()
assert result.token_usage is not None assert result.token_usage is not None
assert result.token_usage.total_tokens == 289 assert result.token_usage.total_tokens == 297
assert result.token_usage.prompt_tokens == 173 assert result.token_usage.prompt_tokens == 173
assert result.token_usage.completion_tokens == 116 assert result.token_usage.completion_tokens == 124
assert result.token_usage.successful_requests == 1 assert result.token_usage.successful_requests == 1
assert result.token_usage.cached_prompt_tokens == 0 assert result.token_usage.cached_prompt_tokens == 0

View File

@@ -38,6 +38,7 @@ extend-exclude = [
"lib/crewai/src/crewai/cli/templates", "lib/crewai/src/crewai/cli/templates",
"lib/crewai/tests/", "lib/crewai/tests/",
"lib/crewai-tools/tests/", "lib/crewai-tools/tests/",
"conftest.py",
] ]
respect-gitignore = true respect-gitignore = true
force-exclude = true force-exclude = true