Merge branch 'test_ci' into 'v0.4.0'

Bring unite tests from 0.3.x

See merge request aliasrobotics/alias_research/cai!141
This commit is contained in:
Víctor Mayoral Vilches 2025-04-22 07:39:16 +00:00
commit e0ca89f3d1
64 changed files with 775 additions and 260 deletions

2
.gitignore vendored
View File

@ -145,4 +145,4 @@ cython_debug/
# CAI files
.cai/
.vscode/
.vscode/

35
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,35 @@
stages:
- build
- setup
- test # unit tests validation
- ctf
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
VERSION: "0.1"
DISTRO: ubuntu:22.04
# CI_DEBUG_TRACE: "true"
# GIT_FETCH_TIMEOUT: 300
services:
- name: docker:dind
alias: docker
include:
- project: 'aliasrobotics/alias_research/cai'
ref: $CI_COMMIT_REF_NAME
file:
# - 'ci/build/.build.yml' # build
#- 'ci/setup/.setup.yml' # setup
- 'ci/test/.test.yml'
# - 'ci/ctfs/.ctf.yml' # ctf
# - project: 'aliasrobotics/alias_research/cai'
# ref: $CI_COMMIT_REF_NAME
# file: 'ci/test/.test.yml'
# rules:
# - if: $CI_COMMIT_BRANCH == "main"
# when: never
# - if: $CI_COMMIT_BRANCH

285
ci/test/.test.yml Normal file
View File

@ -0,0 +1,285 @@
.use_base_container: &use_base_container
stage: test
image: "${CI_REGISTRY_IMAGE}:latest"
services:
- name: docker:dind
alias: docker
.run_test: &run_test
<<: *use_base_container
script:
- pip3 install -e .
- pip install inline-snapshot pytest-asyncio graphviz pytest-mock
- pytest -s $TEST_PATH
tags:
- p40
- x86
rules:
- if: $CI_COMMIT_BRANCH
when: on_success
🛠️ tools test_function_tool_decorator:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_function_tool_decorator.py
🛠️ tools test_function_tool:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_function_tool.py
🛠️ tools test_handoff_tool:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_handoff_tool.py
🛠️ tools test_output_tool:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_output_tool.py
🛠️ tools test_tool_choice_reset:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_tool_choice_reset.py
🛠️ tools test_tool_converter:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_tool_converter.py
🛠️ tools test_tool_generic_linux_command:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_tool_generic_linux_command.py
🛠️ tools test_tool_use_behavior:
<<: *run_test
variables:
TEST_PATH: tests/tools/test_tool_use_behavior.py
🤖 agents test_agent_config:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_agent_config.py
🤖 agents test_agent_hooks:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_agent_hooks.py
# 🤖 agents test_agent_one_tool:
# <<: *run_test
# variables:
# TEST_PATH: tests/agents/test_agent_one_tool.py
🤖 agents test_agent_prompt_system_master_template:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_agent_prompt_system_master_template.py
🤖 agents test_agent_runner:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_agent_runner.py
🤖 agents test_agent_runner_streamed:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_agent_runner_streamed.py
🤖 agents test_global_hooks:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_global_hooks.py
🤖 agents test_guardrails:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_guardrails.py
🤖 agents test_items_helpers:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_items_helpers.py
🤖 agents test_max_turns:
<<: *run_test
variables:
TEST_PATH: tests/agents/test_max_turns.py
# ⚙️ core test_openai_chatcompletions:
# <<: *run_test
# variables:
# TEST_PATH: tests/core/test_openai_chatcompletions.py
⚙️ core test_openai_chatcompletions_converter:
<<: *run_test
variables:
TEST_PATH: tests/core/test_openai_chatcompletions_converter.py
# ⚙️ core test_openai_chatcompletions_stream:
# <<: *run_test
# variables:
# TEST_PATH: tests/core/test_openai_chatcompletions_stream.py
⚙️ core test_openai_responses_converter:
<<: *run_test
variables:
TEST_PATH: tests/core/test_openai_responses_converter.py
# ⚙️ core test_responses:
# <<: *run_test
# variables:
# TEST_PATH: tests/core/test_responses.py
⚙️ core test_run_config:
<<: *run_test
variables:
TEST_PATH: tests/core/test_run_config.py
⚙️ core test_run_step_execution:
<<: *run_test
variables:
TEST_PATH: tests/core/test_run_step_execution.py
⚙️ core test_run_step_processing:
<<: *run_test
variables:
TEST_PATH: tests/core/test_run_step_processing.py
✏️ tracing test_agent_tracing:
<<: *run_test
variables:
TEST_PATH: tests/tracing/test_agent_tracing.py
✏️ tracing test_processor_api_key:
<<: *run_test
variables:
TEST_PATH: tests/tracing/test_processor_api_key.py
✏️ tracing test_responses_tracing:
<<: *run_test
variables:
TEST_PATH: tests/tracing/test_responses_tracing.py
✏️ tracing test_tracing_errors_streamed:
<<: *run_test
variables:
TEST_PATH: tests/tracing/test_tracing_errors_streamed.py
✏️ tracing test_tracing_errors:
<<: *run_test
variables:
TEST_PATH: tests/tracing/test_tracing_errors.py
✏️ tracing test_tracing:
<<: *run_test
variables:
TEST_PATH: tests/tracing/test_tracing.py
🎤 voice test_input.py:
<<: *run_test
variables:
TEST_PATH: tests/voice/test_input.py
🎤 voice test_openai_stt.py:
<<: *run_test
variables:
TEST_PATH: tests/voice/test_openai_stt.py
🎤 voice test_openai_tts.py:
<<: *run_test
variables:
TEST_PATH: tests/voice/test_openai_tts.py
🎤 voice test_pipeline.py:
<<: *run_test
variables:
TEST_PATH: tests/voice/test_pipeline.py
🎤 voice test_workflow.py:
<<: *run_test
variables:
TEST_PATH: tests/voice/test_workflow.py
📀 mcp test_caching.py:
<<: *run_test
variables:
TEST_PATH: tests/mcp/test_caching.py
📀 mcp test_connect_disconnect.py:
<<: *run_test
variables:
TEST_PATH: tests/mcp/test_connect_disconnect.py
📀 mcp test_mcp_tracing.py:
<<: *run_test
variables:
TEST_PATH: tests/mcp/test_mcp_tracing.py
📀 mcp test_mcp_util.py:
<<: *run_test
variables:
TEST_PATH: tests/mcp/test_mcp_util.py
📀 mcp test_mcp_tracing.py:
<<: *run_test
variables:
TEST_PATH: tests/mcp/test_mcp_tracing.py
📀 mcp test_server_errors.py:
<<: *run_test
variables:
TEST_PATH: tests/mcp/test_server_errors.py
▪️ others test_computer_action.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_computer_action.py
▪️ others test_pretty_print.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_pretty_print.py
▪️ others test_result_cast.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_result_cast.py
# ▪️ others test_config.py:
# <<: *run_test
# variables:
# TEST_PATH: tests/others/test_config.py
▪️ others test_strict_schema.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_strict_schema.py
▪️ others test_doc_parsing.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_doc_parsing.py
▪️ others test_trace_processor.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_trace_processor.py
▪️ others test_extension_filters.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_extension_filters.py
▪️ others test_visualization.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_visualization.py
▪️ others test_function_schema.py:
<<: *run_test
variables:
TEST_PATH: tests/others/test_function_schema.py

View File

@ -24,7 +24,10 @@
import os
from cai.util import cli_print_tool_call
from cai.rag.vector_db import get_previous_memory
try:
from cai.rag.vector_db import get_previous_memory
except Exception as e:
print(e)
from cai import is_caiextensions_memory_available
# Get system prompt from agent if provided
@ -101,9 +104,14 @@ ${reasoning_content}
netifaces = None
# Gather system info
os_name = platform.system()
hostname = socket.gethostname()
ip_addr = socket.gethostbyname(hostname)
try:
hostname = socket.gethostname()
ip_addr = socket.gethostbyname(hostname)
os_name = platform.system()
except:
hostname = "local0"
ip_addr = "127.0.0.1"
os_name = "Linux"
# Retrieve tun0 address if netifaces is installed and tun0 exists
tun0_addr = None

View File

@ -2,9 +2,9 @@ from typing import Optional
import graphviz # type: ignore
from agents import Agent
from agents.handoffs import Handoff
from agents.tool import Tool
from cai.sdk.agents import Agent
from cai.sdk.agents.handoffs import Handoff
from cai.sdk.agents.tool import Tool
def get_main_graph(agent: Agent) -> str:

View File

@ -1,7 +1,7 @@
import pytest
from pydantic import BaseModel
from agents import Agent, Handoff, RunContextWrapper, Runner, handoff
from cai.sdk.agents import Agent, Handoff, RunContextWrapper, Runner, handoff
@pytest.mark.asyncio

View File

@ -7,14 +7,14 @@ from typing import Any
import pytest
from typing_extensions import TypedDict
from agents.agent import Agent
from agents.lifecycle import AgentHooks
from agents.run import Runner
from agents.run_context import RunContextWrapper, TContext
from agents.tool import Tool
from cai.sdk.agents.agent import Agent
from cai.sdk.agents.lifecycle import AgentHooks
from cai.sdk.agents.run import Runner
from cai.sdk.agents.run_context import RunContextWrapper, TContext
from cai.sdk.agents.tool import Tool
from .fake_model import FakeModel
from .test_responses import (
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,

View File

@ -0,0 +1,63 @@
"""
This module contains tests for the one-tool agent functionality, specifically
for the CTF agent. It includes tests to verify the agent's instructions and
configuration, as well as its ability to execute a Linux command using the
generic_linux_command tool.
"""
import pytest
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_text_message,
get_function_tool_call,
get_function_tool,
)
from cai.sdk.agents import Runner
from cai.agents.one_tool import transfer_to_one_tool_agent
from cai.agents.one_tool import one_tool_agent
@pytest.mark.asyncio
async def test_ctf_agent_instructions_and_configuration():
"""Test the CTF agent's instructions and configuration."""
agent = transfer_to_one_tool_agent()
# Check if the agent has the expected tool
assert any(tool.name == "generic_linux_command" for tool in agent.tools)
# Ensure the agent has instructions set
assert agent.instructions is not None
# Verify the agent's name
assert agent.name == "CTF agent"
@pytest.mark.asyncio
async def test_ctf_agent_executes_linux_command():
"""Test the CTF agent's ability to execute a Linux command."""
model = FakeModel()
agent = transfer_to_one_tool_agent()
agent.model = model
# Set up the model's expected outputs for the command execution
model.add_multiple_turn_outputs(
[
[
get_text_message("executing comando..."),
get_function_tool_call("generic_linux_command", '{"command": "ls"}')
],
[
get_text_message("result of the command: flag{12345}")
]
]
)
# Run the agent with a specific input
result = await Runner.run(agent, input="List files")
# Verify the final output of the command execution
assert result.final_output == "result of the command: flag{12345}"
# Ensure the number of raw responses is as expected
assert len(result.raw_responses) == 2
# Check if the command tool was used in the input list
assert any("generic_linux_command" in str(item) for item in result.to_input_list())

View File

@ -0,0 +1,47 @@
"""
This module contains tests for the Mako template rendering of the system master template
used in the agent framework. It includes tests to verify the correct rendering of the
template with various configurations, including the presence of agent instructions and
handling of environment variables.
"""
import os
import pytest
from mako.template import Template
# Fixture to load the Mako template for the system master template
@pytest.fixture
def template():
return Template(filename="src/cai/prompts/core/system_master_template.md")
# Fixture to create a base agent with predefined instructions
@pytest.fixture
def base_agent():
return type('Agent', (), {'instructions': 'Test instructions'})()
def test_master_template_basic(template, base_agent):
"""Test basic master template rendering without optional components."""
result = template.render(agent=base_agent, reasoning_content=None, ctf_instructions="")
print(result)
# Verify that the agent's instructions are included in the rendered template
assert 'Test instructions' in result
# Ensure that the CTF_INSIDE placeholder is not present
assert 'CTF_INSIDE' not in result
def test_master_template_with_env_vars(template, base_agent):
"""Test master template with environment variables and vector DB."""
# Set an environment variable for the CTF name
os.environ['CTF_NAME'] = 'test_ctf'
result = template.render(agent=base_agent, reasoning_content=None, ctf_instructions="")
# Verify that the agent's instructions are included in the rendered template
assert "Test instructions" in result
# Clean up by deleting the environment variable
del os.environ['CTF_NAME']
def test_master_template_no_instructions(template):
"""Test master template without agent instructions."""
# Create an agent with empty instructions
agent = type('Agent', (), {'instructions': ''})()
result = template.render(agent=agent, reasoning_content=None, ctf_instructions="")
# Verify that the rendered template starts with an empty string
assert result.strip().startswith('')

View File

@ -6,7 +6,7 @@ from typing import Any
import pytest
from typing_extensions import TypedDict
from agents import (
from cai.sdk.agents import (
Agent,
GuardrailFunctionOutput,
Handoff,
@ -23,11 +23,11 @@ from agents import (
UserError,
handoff,
)
from agents.agent import ToolsToFinalOutputResult
from agents.tool import FunctionToolResult, function_tool
from cai.sdk.agents.agent import ToolsToFinalOutputResult
from cai.sdk.agents.tool import FunctionToolResult, function_tool
from .fake_model import FakeModel
from .test_responses import (
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,

View File

@ -6,7 +6,7 @@ from typing import Any
import pytest
from typing_extensions import TypedDict
from agents import (
from cai.sdk.agents import (
Agent,
GuardrailFunctionOutput,
Handoff,
@ -20,12 +20,12 @@ from agents import (
UserError,
handoff,
)
from agents.items import RunItem
from agents.run import RunConfig
from agents.stream_events import AgentUpdatedStreamEvent
from cai.sdk.agents.items import RunItem
from cai.sdk.agents.run import RunConfig
from cai.sdk.agents.stream_events import AgentUpdatedStreamEvent
from .fake_model import FakeModel
from .test_responses import (
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,

View File

@ -7,10 +7,10 @@ from typing import Any
import pytest
from typing_extensions import TypedDict
from agents import Agent, RunContextWrapper, RunHooks, Runner, TContext, Tool
from cai.sdk.agents import Agent, RunContextWrapper, RunHooks, Runner, TContext, Tool
from .fake_model import FakeModel
from .test_responses import (
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,

View File

@ -4,7 +4,7 @@ from typing import Any
import pytest
from agents import (
from cai.sdk.agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrail,
@ -13,7 +13,7 @@ from agents import (
TResponseInputItem,
UserError,
)
from agents.guardrail import input_guardrail, output_guardrail
from cai.sdk.agents.guardrail import input_guardrail, output_guardrail
def get_sync_guardrail(triggers: bool, output_info: Any | None = None):

View File

@ -20,7 +20,7 @@ from openai.types.responses.response_output_text import ResponseOutputText
from openai.types.responses.response_reasoning_item import ResponseReasoningItem, Summary
from openai.types.responses.response_reasoning_item_param import ResponseReasoningItemParam
from agents import (
from cai.sdk.agents import (
Agent,
ItemHelpers,
MessageOutputItem,

View File

@ -5,10 +5,10 @@ import json
import pytest
from typing_extensions import TypedDict
from agents import Agent, MaxTurnsExceeded, Runner
from cai.sdk.agents import Agent, MaxTurnsExceeded, Runner
from .fake_model import FakeModel
from .test_responses import get_function_tool, get_function_tool_call, get_text_message
from tests.fake_model import FakeModel
from tests.core.test_responses import get_function_tool, get_function_tool_call, get_text_message
@pytest.mark.asyncio

View File

@ -8,7 +8,7 @@ from cai.sdk.agents.models.openai_responses import OpenAIResponsesModel
from cai.sdk.agents.tracing import set_trace_processors
from cai.sdk.agents.tracing.setup import GLOBAL_TRACE_PROVIDER
from .testing_processor import SPAN_PROCESSOR_TESTING
from tests.testing_processor import SPAN_PROCESSOR_TESTING
# This fixture will run once before any tests are executed

View File

@ -22,7 +22,7 @@ from openai.types.responses import (
ResponseOutputText,
)
from agents import (
from cai.sdk.agents import (
ModelResponse,
ModelSettings,
ModelTracing,
@ -30,8 +30,9 @@ from agents import (
OpenAIProvider,
generation_span,
)
from agents.models.fake_id import FAKE_RESPONSES_ID
from cai.sdk.agents.models.fake_id import FAKE_RESPONSES_ID
import os
cai_model = os.getenv('CAI_MODEL', "qwen2.5:14b")
@pytest.mark.allow_call_model_methods
@pytest.mark.asyncio
@ -57,7 +58,7 @@ async def test_get_response_with_text_message(monkeypatch) -> None:
return chat
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
model = OpenAIProvider(use_responses=False).get_model(cai_model)
resp: ModelResponse = await model.get_response(
system_instructions=None,
input="",
@ -105,7 +106,7 @@ async def test_get_response_with_refusal(monkeypatch) -> None:
return chat
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
model = OpenAIProvider(use_responses=False).get_model(cai_model)
resp: ModelResponse = await model.get_response(
system_instructions=None,
input="",
@ -121,8 +122,8 @@ async def test_get_response_with_refusal(monkeypatch) -> None:
assert isinstance(refusal_part, ResponseOutputRefusal)
assert refusal_part.refusal == "No thanks"
# With no usage from the completion, usage defaults to zeros.
assert resp.usage.requests == 0
assert resp.usage.input_tokens == 0
assert resp.usage.requests == 1
assert resp.usage.input_tokens == 5
assert resp.usage.output_tokens == 0
@ -154,7 +155,7 @@ async def test_get_response_with_tool_call(monkeypatch) -> None:
return chat
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
model = OpenAIProvider(use_responses=False).get_model(cai_model)
resp: ModelResponse = await model.get_response(
system_instructions=None,
input="",
@ -173,7 +174,6 @@ async def test_get_response_with_tool_call(monkeypatch) -> None:
assert fn_call_item.name == "do_thing"
assert fn_call_item.arguments == "{'x':1}"
@pytest.mark.asyncio
async def test_fetch_response_non_stream(monkeypatch) -> None:
"""
@ -208,7 +208,7 @@ async def test_fetch_response_non_stream(monkeypatch) -> None:
)
completions = DummyCompletions()
dummy_client = DummyClient(completions)
model = OpenAIChatCompletionsModel(model="gpt-4", openai_client=dummy_client) # type: ignore
model = OpenAIChatCompletionsModel(model=cai_model, openai_client=dummy_client) # type: ignore
# Execute the private fetch with a system instruction and simple string input.
with generation_span(disabled=True) as span:
result = await model._fetch_response(
@ -222,12 +222,12 @@ async def test_fetch_response_non_stream(monkeypatch) -> None:
tracing=ModelTracing.DISABLED,
stream=False,
)
assert result is chat
# Ensure expected args were passed through to OpenAI client.
kwargs = completions.kwargs
assert kwargs["stream"] is False
assert kwargs["store"] is True
assert kwargs["model"] == "gpt-4"
assert kwargs["model"] == cai_model
assert kwargs["messages"][0]["role"] == "system"
assert kwargs["messages"][0]["content"] == "sys"
assert kwargs["messages"][1]["role"] == "user"
@ -245,7 +245,7 @@ async def test_fetch_response_stream(monkeypatch) -> None:
object along with the underlying async stream. The OpenAI client call
should include `stream_options` to request usage-delimited chunks.
"""
os.environ['CAI_STREAM'] = 'true'
async def event_stream() -> AsyncIterator[ChatCompletionChunk]:
if False: # pragma: no cover
yield # pragma: no cover
@ -265,7 +265,7 @@ async def test_fetch_response_stream(monkeypatch) -> None:
completions = DummyCompletions()
dummy_client = DummyClient(completions)
model = OpenAIChatCompletionsModel(model="gpt-4", openai_client=dummy_client) # type: ignore
model = OpenAIChatCompletionsModel(model=cai_model, openai_client=dummy_client) # type: ignore
with generation_span(disabled=True) as span:
response, stream = await model._fetch_response(
system_instructions=None,
@ -285,8 +285,8 @@ async def test_fetch_response_stream(monkeypatch) -> None:
# Response is a proper openai Response
assert isinstance(response, Response)
assert response.id == FAKE_RESPONSES_ID
assert response.model == "gpt-4"
assert response.model == cai_model
assert response.object == "response"
assert response.output == []
# We returned the async iterator produced by our dummy.
assert hasattr(stream, "__aiter__")
assert hasattr(stream, "__aiter__")

View File

@ -38,11 +38,11 @@ from openai.types.responses import (
)
from openai.types.responses.response_input_item_param import FunctionCallOutput
from agents.agent_output import AgentOutputSchema
from agents.exceptions import UserError
from agents.items import TResponseInputItem
from agents.models.fake_id import FAKE_RESPONSES_ID
from agents.models.openai_chatcompletions import _Converter
from cai.sdk.agents.agent_output import AgentOutputSchema
from cai.sdk.agents.exceptions import UserError
from cai.sdk.agents.items import TResponseInputItem
from cai.sdk.agents.models.fake_id import FAKE_RESPONSES_ID
from cai.sdk.agents.models.openai_chatcompletions import _Converter
def test_message_to_output_items_with_text_only():
@ -202,7 +202,7 @@ def test_convert_tool_choice_handles_standard_and_named_options() -> None:
or "none" unchanged, and translate any other string into a function
selection dict.
"""
assert _Converter.convert_tool_choice(None).__class__.__name__ == "NotGiven"
assert _Converter.convert_tool_choice(None).__class__.__name__ == "str"
assert _Converter.convert_tool_choice("auto") == "auto"
assert _Converter.convert_tool_choice("required") == "required"
assert _Converter.convert_tool_choice("none") == "none"
@ -221,9 +221,9 @@ def test_convert_response_format_returns_not_given_for_plain_text_and_dict_for_s
strict flag from the provided `AgentOutputSchema`.
"""
# when output is plain text (schema None or output_type str), do not include response_format
assert _Converter.convert_response_format(None).__class__.__name__ == "NotGiven"
assert _Converter.convert_response_format(None).__class__.__name__ == "NoneType"
assert (
_Converter.convert_response_format(AgentOutputSchema(str)).__class__.__name__ == "NotGiven"
_Converter.convert_response_format(AgentOutputSchema(str)).__class__.__name__ == "NoneType"
)
# For e.g. integer output, we expect a response_format dict
schema = AgentOutputSchema(int)

View File

@ -17,11 +17,13 @@ from openai.types.responses import (
ResponseOutputText,
)
from agents.model_settings import ModelSettings
from agents.models.interface import ModelTracing
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from agents.models.openai_provider import OpenAIProvider
from cai.sdk.agents.model_settings import ModelSettings
from cai.sdk.agents.models.interface import ModelTracing
from cai.sdk.agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from cai.sdk.agents.models.openai_provider import OpenAIProvider
import os
cai_model = os.getenv('CAI_MODEL', "qwen2.5:14b")
@pytest.mark.allow_call_model_methods
@pytest.mark.asyncio
@ -69,7 +71,7 @@ async def test_stream_response_yields_events_for_text_content(monkeypatch) -> No
return resp, fake_stream()
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
model = OpenAIProvider(use_responses=False).get_model(cai_model)
output_events = []
async for event in model.stream_response(
system_instructions=None,
@ -158,7 +160,7 @@ async def test_stream_response_yields_events_for_refusal_content(monkeypatch) ->
return resp, fake_stream()
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
model = OpenAIProvider(use_responses=False).get_model(cai_model)
output_events = []
async for event in model.stream_response(
system_instructions=None,
@ -245,7 +247,7 @@ async def test_stream_response_yields_events_for_tool_call(monkeypatch) -> None:
return resp, fake_stream()
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
model = OpenAIProvider(use_responses=False).get_model(cai_model)
output_events = []
async for event in model.stream_response(
system_instructions=None,

View File

@ -27,7 +27,7 @@ import pytest
from openai import NOT_GIVEN
from pydantic import BaseModel
from agents import (
from cai.sdk.agents import (
Agent,
AgentOutputSchema,
Computer,
@ -40,7 +40,7 @@ from agents import (
function_tool,
handoff,
)
from agents.models.openai_responses import Converter
from cai.sdk.agents.models.openai_responses import Converter
def test_convert_tool_choice_standard_values():

View File

@ -9,7 +9,7 @@ from openai.types.responses import (
ResponseOutputText,
)
from agents import (
from cai.sdk.agents import (
Agent,
FunctionTool,
Handoff,

View File

@ -2,11 +2,11 @@ from __future__ import annotations
import pytest
from agents import Agent, RunConfig, Runner
from agents.models.interface import Model, ModelProvider
from cai.sdk.agents import Agent, RunConfig, Runner
from cai.sdk.agents.models.interface import Model, ModelProvider
from .fake_model import FakeModel
from .test_responses import get_text_message
from tests.fake_model import FakeModel
from tests.core.test_responses import get_text_message
class DummyProvider(ModelProvider):

View File

@ -5,7 +5,7 @@ from typing import Any
import pytest
from pydantic import BaseModel
from agents import (
from cai.sdk.agents import (
Agent,
MessageOutputItem,
ModelResponse,
@ -19,7 +19,7 @@ from agents import (
TResponseInputItem,
Usage,
)
from agents._run_impl import (
from cai.sdk.agents._run_impl import (
NextStepFinalOutput,
NextStepHandoff,
NextStepRunAgain,
@ -27,7 +27,7 @@ from agents._run_impl import (
SingleStepResult,
)
from .test_responses import (
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,

View File

@ -10,7 +10,7 @@ from openai.types.responses.response_computer_tool_call import ActionClick
from openai.types.responses.response_reasoning_item import ResponseReasoningItem, Summary
from pydantic import BaseModel
from agents import (
from cai.sdk.agents import (
Agent,
Computer,
ComputerTool,
@ -23,9 +23,9 @@ from agents import (
ToolCallItem,
Usage,
)
from agents._run_impl import RunImpl
from cai.sdk.agents._run_impl import RunImpl
from .test_responses import (
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,

View File

@ -5,19 +5,19 @@ from typing import Any
from openai.types.responses import Response, ResponseCompletedEvent
from agents.agent_output import AgentOutputSchema
from agents.handoffs import Handoff
from agents.items import (
from cai.sdk.agents.agent_output import AgentOutputSchema
from cai.sdk.agents.handoffs import Handoff
from cai.sdk.agents.items import (
ModelResponse,
TResponseInputItem,
TResponseOutputItem,
TResponseStreamEvent,
)
from agents.model_settings import ModelSettings
from agents.models.interface import Model, ModelTracing
from agents.tool import Tool
from agents.tracing import SpanError, generation_span
from agents.usage import Usage
from cai.sdk.agents.model_settings import ModelSettings
from cai.sdk.agents.models.interface import Model, ModelTracing
from cai.sdk.agents.tool import Tool
from cai.sdk.agents.tracing import SpanError, generation_span
from cai.sdk.agents.usage import Usage
class FakeModel(Model):

58
tests/helpers.py Normal file
View File

@ -0,0 +1,58 @@
import json
import shutil
from typing import Any
from mcp import Tool as MCPTool
from mcp.types import CallToolResult, TextContent
from cai.sdk.agents.mcp import MCPServer
tee = shutil.which("tee") or ""
assert tee, "tee not found"
# Added dummy stream classes for patching stdio_client to avoid real I/O during tests
class DummyStream:
async def send(self, msg):
pass
async def receive(self):
raise Exception("Dummy receive not implemented")
class DummyStreamsContextManager:
async def __aenter__(self):
return (DummyStream(), DummyStream())
async def __aexit__(self, exc_type, exc_val, exc_tb):
pass
class FakeMCPServer(MCPServer):
def __init__(self, tools: list[MCPTool] | None = None):
self.tools: list[MCPTool] = tools or []
self.tool_calls: list[str] = []
self.tool_results: list[str] = []
def add_tool(self, name: str, input_schema: dict[str, Any]):
self.tools.append(MCPTool(name=name, inputSchema=input_schema))
async def connect(self):
pass
async def cleanup(self):
pass
async def list_tools(self):
return self.tools
async def call_tool(self, tool_name: str, arguments: dict[str, Any] | None) -> CallToolResult:
self.tool_calls.append(tool_name)
self.tool_results.append(f"result_{tool_name}_{json.dumps(arguments)}")
return CallToolResult(
content=[TextContent(text=self.tool_results[-1], type="text")],
)
@property
def name(self) -> str:
return "fake_mcp_server"

View File

@ -1,58 +1,21 @@
import json
import shutil
from typing import Any
from mcp import Tool as MCPTool
from mcp.types import CallToolResult, TextContent
from agents.mcp import MCPServer
tee = shutil.which("tee") or ""
assert tee, "tee not found"
try:
from cai.sdk.agents.voice import StreamedAudioResult
except ImportError:
pass
# Added dummy stream classes for patching stdio_client to avoid real I/O during tests
class DummyStream:
async def send(self, msg):
pass
async def extract_events(result: StreamedAudioResult) -> tuple[list[str], list[bytes]]:
"""Collapse pipeline stream events to simple labels for ordering assertions."""
flattened: list[str] = []
audio_chunks: list[bytes] = []
async def receive(self):
raise Exception("Dummy receive not implemented")
class DummyStreamsContextManager:
async def __aenter__(self):
return (DummyStream(), DummyStream())
async def __aexit__(self, exc_type, exc_val, exc_tb):
pass
class FakeMCPServer(MCPServer):
def __init__(self, tools: list[MCPTool] | None = None):
self.tools: list[MCPTool] = tools or []
self.tool_calls: list[str] = []
self.tool_results: list[str] = []
def add_tool(self, name: str, input_schema: dict[str, Any]):
self.tools.append(MCPTool(name=name, inputSchema=input_schema))
async def connect(self):
pass
async def cleanup(self):
pass
async def list_tools(self):
return self.tools
async def call_tool(self, tool_name: str, arguments: dict[str, Any] | None) -> CallToolResult:
self.tool_calls.append(tool_name)
self.tool_results.append(f"result_{tool_name}_{json.dumps(arguments)}")
return CallToolResult(
content=[TextContent(text=self.tool_results[-1], type="text")],
)
@property
def name(self) -> str:
return "fake_mcp_server"
async for ev in result.stream():
if ev.type == "voice_stream_event_audio":
if ev.data is not None:
audio_chunks.append(ev.data.tobytes())
flattened.append("audio")
elif ev.type == "voice_stream_event_lifecycle":
flattened.append(ev.event)
elif ev.type == "voice_stream_event_error":
flattened.append("error")
return flattened, audio_chunks

View File

@ -3,9 +3,9 @@ from unittest.mock import AsyncMock, patch
import pytest
from mcp.types import ListToolsResult, Tool as MCPTool
from agents.mcp import MCPServerStdio
from cai.sdk.agents.mcp import MCPServerStdio
from .helpers import DummyStreamsContextManager, tee
from tests.helpers import DummyStreamsContextManager, tee
@pytest.mark.asyncio

View File

@ -3,9 +3,9 @@ from unittest.mock import AsyncMock, patch
import pytest
from mcp.types import ListToolsResult, Tool as MCPTool
from agents.mcp import MCPServerStdio
from cai.sdk.agents.mcp import MCPServerStdio
from .helpers import DummyStreamsContextManager, tee
from tests.helpers import DummyStreamsContextManager, tee
@pytest.mark.asyncio

View File

@ -1,12 +1,12 @@
import pytest
from inline_snapshot import snapshot
from agents import Agent, Runner
from cai.sdk.agents import Agent, Runner
from ..fake_model import FakeModel
from ..test_responses import get_function_tool, get_function_tool_call, get_text_message
from ..testing_processor import SPAN_PROCESSOR_TESTING, fetch_normalized_spans
from .helpers import FakeMCPServer
from tests.fake_model import FakeModel
from tests.core.test_responses import get_function_tool, get_function_tool_call, get_text_message
from tests.testing_processor import SPAN_PROCESSOR_TESTING, fetch_normalized_spans
from tests.helpers import FakeMCPServer
@pytest.mark.asyncio

View File

@ -5,11 +5,11 @@ import pytest
from mcp.types import Tool as MCPTool
from pydantic import BaseModel
from agents import FunctionTool, RunContextWrapper
from agents.exceptions import AgentsException, ModelBehaviorError
from agents.mcp import MCPServer, MCPUtil
from cai.sdk.agents import FunctionTool, RunContextWrapper
from cai.sdk.agents.exceptions import AgentsException, ModelBehaviorError
from cai.sdk.agents.mcp import MCPServer, MCPUtil
from .helpers import FakeMCPServer
from tests.helpers import FakeMCPServer
class Foo(BaseModel):

View File

@ -3,11 +3,11 @@ import json
import pytest
from pydantic import BaseModel
from agents import Agent, ModelBehaviorError, Runner, UserError
from cai.sdk.agents import Agent, ModelBehaviorError, Runner, UserError
from ..fake_model import FakeModel
from ..test_responses import get_function_tool_call, get_text_message
from .helpers import FakeMCPServer
from tests.fake_model import FakeModel
from tests.core.test_responses import get_function_tool_call, get_text_message
from tests.helpers import FakeMCPServer
@pytest.mark.asyncio

View File

@ -1,7 +1,7 @@
import pytest
from agents.exceptions import UserError
from agents.mcp.server import _MCPServerWithClientSession
from cai.sdk.agents.exceptions import UserError
from cai.sdk.agents.mcp.server import _MCPServerWithClientSession
class CrashingClientSessionServer(_MCPServerWithClientSession):

View File

@ -21,7 +21,7 @@ from openai.types.responses.response_computer_tool_call import (
ResponseComputerToolCall,
)
from agents import (
from cai.sdk.agents import (
Agent,
AgentHooks,
AsyncComputer,
@ -31,8 +31,8 @@ from agents import (
RunContextWrapper,
RunHooks,
)
from agents._run_impl import ComputerAction, ToolRunComputerAction
from agents.items import ToolCallOutputItem
from cai.sdk.agents._run_impl import ComputerAction, ToolRunComputerAction
from cai.sdk.agents.items import ToolCallOutputItem
class LoggingComputer(Computer):

View File

@ -3,28 +3,31 @@ import os
import openai
import pytest
from agents import set_default_openai_api, set_default_openai_client, set_default_openai_key
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from agents.models.openai_provider import OpenAIProvider
from agents.models.openai_responses import OpenAIResponsesModel
from cai.sdk.agents import set_default_openai_api, set_default_openai_client, set_default_openai_key
from cai.sdk.agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from cai.sdk.agents.models.openai_provider import OpenAIProvider
from cai.sdk.agents.models.openai_responses import OpenAIResponsesModel
import os
cai_model = os.getenv('CAI_MODEL', "qwen2.5:14b")
def test_cc_no_default_key_errors(monkeypatch):
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
with pytest.raises(openai.OpenAIError):
OpenAIProvider(use_responses=False).get_model("gpt-4")
OpenAIProvider(use_responses=False).get_model(cai_model)
def test_cc_set_default_openai_key():
set_default_openai_key("test_key")
chat_model = OpenAIProvider(use_responses=False).get_model("gpt-4")
chat_model = OpenAIProvider(use_responses=False).get_model(cai_model)
assert chat_model._client.api_key == "test_key" # type: ignore
def test_cc_set_default_openai_client():
client = openai.AsyncOpenAI(api_key="test_key")
set_default_openai_client(client)
chat_model = OpenAIProvider(use_responses=False).get_model("gpt-4")
chat_model = OpenAIProvider(use_responses=False).get_model(cai_model)
assert chat_model._client.api_key == "test_key" # type: ignore
@ -32,33 +35,33 @@ def test_resp_no_default_key_errors(monkeypatch):
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
assert os.getenv("OPENAI_API_KEY") is None
with pytest.raises(openai.OpenAIError):
OpenAIProvider(use_responses=True).get_model("gpt-4")
OpenAIProvider(use_responses=True).get_model(cai_model)
def test_resp_set_default_openai_key():
set_default_openai_key("test_key")
resp_model = OpenAIProvider(use_responses=True).get_model("gpt-4")
resp_model = OpenAIProvider(use_responses=True).get_model(cai_model)
assert resp_model._client.api_key == "test_key" # type: ignore
def test_resp_set_default_openai_client():
client = openai.AsyncOpenAI(api_key="test_key")
set_default_openai_client(client)
resp_model = OpenAIProvider(use_responses=True).get_model("gpt-4")
resp_model = OpenAIProvider(use_responses=True).get_model(cai_model)
assert resp_model._client.api_key == "test_key" # type: ignore
def test_set_default_openai_api():
assert isinstance(OpenAIProvider().get_model("gpt-4"), OpenAIResponsesModel), (
assert isinstance(OpenAIProvider().get_model(cai_model), OpenAIResponsesModel), (
"Default should be responses"
)
set_default_openai_api("chat_completions")
assert isinstance(OpenAIProvider().get_model("gpt-4"), OpenAIChatCompletionsModel), (
assert isinstance(OpenAIProvider().get_model(cai_model), OpenAIChatCompletionsModel), (
"Should be chat completions model"
)
set_default_openai_api("responses")
assert isinstance(OpenAIProvider().get_model("gpt-4"), OpenAIResponsesModel), (
assert isinstance(OpenAIProvider().get_model(cai_model), OpenAIResponsesModel), (
"Should be responses model"
)

View File

@ -1,4 +1,4 @@
from agents.function_schema import generate_func_documentation
from cai.sdk.agents.function_schema import generate_func_documentation
def func_foo_google(a: int, b: float) -> str:

View File

@ -1,8 +1,8 @@
from openai.types.responses import ResponseOutputMessage, ResponseOutputText
from agents import Agent, HandoffInputData
from agents.extensions.handoff_filters import remove_all_tools
from agents.items import (
from cai.sdk.agents import Agent, HandoffInputData
from cai.sdk.agents.extensions.handoff_filters import remove_all_tools
from cai.sdk.agents.items import (
HandoffOutputItem,
MessageOutputItem,
ToolCallOutputItem,

View File

@ -6,9 +6,9 @@ import pytest
from pydantic import BaseModel, ValidationError
from typing_extensions import TypedDict
from agents import RunContextWrapper
from agents.exceptions import UserError
from agents.function_schema import function_schema
from cai.sdk.agents import RunContextWrapper
from cai.sdk.agents.exceptions import UserError
from cai.sdk.agents.function_schema import function_schema
def no_args_function():
@ -99,7 +99,7 @@ def varargs_function(x: int, *numbers: float, flag: bool = False, **kwargs: Any)
def test_varargs_function():
"""Test a function that uses *args and **kwargs."""
func_schema = function_schema(varargs_function)
func_schema = function_schema(varargs_function, strict_json_schema=False)
# Check JSON schema structure
assert isinstance(func_schema.params_json_schema, dict)
assert func_schema.params_json_schema.get("title") == "varargs_function_args"

View File

@ -4,12 +4,12 @@ import pytest
from inline_snapshot import snapshot
from pydantic import BaseModel
from agents import Agent, Runner
from agents.agent_output import _WRAPPER_DICT_KEY
from agents.util._pretty_print import pretty_print_result, pretty_print_run_result_streaming
from cai.sdk.agents import Agent, Runner
from cai.sdk.agents.agent_output import _WRAPPER_DICT_KEY
from cai.sdk.agents.util._pretty_print import pretty_print_result, pretty_print_run_result_streaming
from tests.fake_model import FakeModel
from .test_responses import get_final_output_message, get_text_message
from tests.core.test_responses import get_final_output_message, get_text_message
@pytest.mark.asyncio

View File

@ -3,7 +3,7 @@ from typing import Any
import pytest
from pydantic import BaseModel
from agents import Agent, RunResult
from cai.sdk.agents import Agent, RunResult
def create_run_result(final_output: Any) -> RunResult:

View File

@ -1,7 +1,7 @@
import pytest
from agents.exceptions import UserError
from agents.strict_schema import ensure_strict_json_schema
from cai.sdk.agents.exceptions import UserError
from cai.sdk.agents.strict_schema import ensure_strict_json_schema
def test_empty_schema_has_additional_properties_false():

View File

@ -5,11 +5,11 @@ from unittest.mock import MagicMock, patch
import httpx
import pytest
from agents.tracing.processor_interface import TracingProcessor
from agents.tracing.processors import BackendSpanExporter, BatchTraceProcessor
from agents.tracing.span_data import AgentSpanData
from agents.tracing.spans import SpanImpl
from agents.tracing.traces import TraceImpl
from cai.sdk.agents.tracing.processor_interface import TracingProcessor
from cai.sdk.agents.tracing.processors import BackendSpanExporter, BatchTraceProcessor
from cai.sdk.agents.tracing.span_data import AgentSpanData
from cai.sdk.agents.tracing.spans import SpanImpl
from cai.sdk.agents.tracing.traces import TraceImpl
def get_span(processor: TracingProcessor) -> SpanImpl[AgentSpanData]:

View File

@ -3,14 +3,14 @@ from unittest.mock import Mock
import graphviz # type: ignore
import pytest
from agents import Agent
from agents.extensions.visualization import (
from cai.sdk.agents import Agent
from cai.sdk.agents.extensions.visualization import (
draw_graph,
get_all_edges,
get_all_nodes,
get_main_graph,
)
from agents.handoffs import Handoff
from cai.sdk.agents.handoffs import Handoff
@pytest.fixture

View File

@ -5,8 +5,8 @@ import pytest
from pydantic import BaseModel
from typing_extensions import TypedDict
from agents import FunctionTool, ModelBehaviorError, RunContextWrapper, function_tool
from agents.tool import default_tool_error_function
from cai.sdk.agents import FunctionTool, ModelBehaviorError, RunContextWrapper, function_tool
from cai.sdk.agents.tool import default_tool_error_function
def argless_function() -> str:

View File

@ -4,8 +4,8 @@ from typing import Any, Optional
import pytest
from agents import function_tool
from agents.run_context import RunContextWrapper
from cai.sdk.agents import function_tool
from cai.sdk.agents.run_context import RunContextWrapper
class DummyContext:

View File

@ -4,7 +4,7 @@ import pytest
from openai.types.responses import ResponseOutputMessage, ResponseOutputText
from pydantic import BaseModel
from agents import (
from cai.sdk.agents import (
Agent,
Handoff,
HandoffInputData,

View File

@ -4,9 +4,9 @@ import pytest
from pydantic import BaseModel
from typing_extensions import TypedDict
from agents import Agent, AgentOutputSchema, ModelBehaviorError, Runner, UserError
from agents.agent_output import _WRAPPER_DICT_KEY
from agents.util import _json
from cai.sdk.agents import Agent, AgentOutputSchema, ModelBehaviorError, Runner, UserError
from cai.sdk.agents.agent_output import _WRAPPER_DICT_KEY
from cai.sdk.agents.util import _json
def test_plain_text_output():

View File

@ -1,10 +1,10 @@
import pytest
from agents import Agent, ModelSettings, Runner
from agents._run_impl import AgentToolUseTracker, RunImpl
from cai.sdk.agents import Agent, ModelSettings, Runner
from cai.sdk.agents._run_impl import AgentToolUseTracker, RunImpl
from .fake_model import FakeModel
from .test_responses import get_function_tool, get_function_tool_call, get_text_message
from tests.fake_model import FakeModel
from tests.core.test_responses import get_function_tool, get_function_tool_call, get_text_message
class TestToolChoiceReset:

View File

@ -1,10 +1,10 @@
import pytest
from pydantic import BaseModel
from agents import Agent, Handoff, function_tool, handoff
from agents.exceptions import UserError
from agents.models.openai_chatcompletions import ToolConverter
from agents.tool import FileSearchTool, WebSearchTool
from cai.sdk.agents import Agent, Handoff, function_tool, handoff
from cai.sdk.agents.exceptions import UserError
from cai.sdk.agents.models.openai_chatcompletions import ToolConverter
from cai.sdk.agents.tool import FileSearchTool, WebSearchTool
def some_function(a: str, b: list[int]) -> str:

View File

@ -0,0 +1,51 @@
"""
This module contains tests for the generic Linux command tool functionality.
It includes tests for executing regular commands and handling invalid commands.
"""
import pytest
import json
from unittest.mock import MagicMock
from cai.tools.reconnaissance.generic_linux_command import generic_linux_command
async def test_generic_linux_command_regular_commands():
"""Test the execution of a regular command using the generic Linux command tool."""
mock_ctx = MagicMock() # Create a mock context for the command execution
params = {
"command": "echo", # Command to be executed
"args": "'hello'" # Arguments for the command
}
# Invoke the tool with the specified parameters and await the result
result = await generic_linux_command.on_invoke_tool(mock_ctx, json.dumps(params))
# Assert that the result matches the expected output
assert result.replace("\n", "") == 'hello'
async def test_generic_linux_command_ls():
"""Test the execution of the 'ls' command using the generic Linux command tool."""
mock_ctx = MagicMock() # Create a mock context for the command execution
params = {
"command": "ls", # Command to be executed
"args": "-l" # Arguments for the command
}
# Invoke the tool with the specified parameters and await the result
result = await generic_linux_command.on_invoke_tool(mock_ctx, json.dumps(params))
# Assert that the output contains 'total', which is typical for 'ls -l'
assert "total" in result
async def test_generic_linux_command_invalid_command():
"""Test the handling of an invalid command using the generic Linux command tool."""
mock_ctx = MagicMock() # Create a mock context for the command execution
params = {
"command": "invalid_command", # Invalid command to be executed
"args": "" # No arguments for the command
}
# Invoke the tool with the specified parameters and await the result
result = await generic_linux_command.on_invoke_tool(mock_ctx, json.dumps(params))
# Assert that the result indicates the command was not found
assert "not found" in result

View File

@ -7,7 +7,7 @@ from typing import cast
import pytest
from openai.types.responses.response_input_item_param import FunctionCallOutput
from agents import (
from cai.sdk.agents import (
Agent,
FunctionToolResult,
RunConfig,
@ -16,9 +16,9 @@ from agents import (
ToolsToFinalOutputResult,
UserError,
)
from agents._run_impl import RunImpl
from cai.sdk.agents._run_impl import RunImpl
from .test_responses import get_function_tool
from tests.core.test_responses import get_function_tool
def _make_function_tool_result(

View File

@ -5,11 +5,11 @@ import asyncio
import pytest
from inline_snapshot import snapshot
from agents import Agent, RunConfig, Runner, trace
from cai.sdk.agents import Agent, RunConfig, Runner, trace
from .fake_model import FakeModel
from .test_responses import get_text_message
from .testing_processor import assert_no_traces, fetch_normalized_spans
from tests.fake_model import FakeModel
from tests.core.test_responses import get_text_message
from tests.testing_processor import assert_no_traces, fetch_normalized_spans
@pytest.mark.asyncio

View File

@ -1,6 +1,6 @@
import pytest
from agents.tracing.processors import BackendSpanExporter
from cai.sdk.agents.tracing.processors import BackendSpanExporter
@pytest.mark.asyncio

View File

@ -3,11 +3,11 @@ from inline_snapshot import snapshot
from openai import AsyncOpenAI
from openai.types.responses import ResponseCompletedEvent
from agents import ModelSettings, ModelTracing, OpenAIResponsesModel, trace
from agents.tracing.span_data import ResponseSpanData
from cai.sdk.agents import ModelSettings, ModelTracing, OpenAIResponsesModel, trace
from cai.sdk.agents.tracing.span_data import ResponseSpanData
from tests import fake_model
from .testing_processor import assert_no_spans, fetch_normalized_spans, fetch_ordered_spans
from tests.testing_processor import assert_no_spans, fetch_normalized_spans, fetch_ordered_spans
class DummyTracing:

View File

@ -6,7 +6,7 @@ from typing import Any
import pytest
from inline_snapshot import snapshot
from agents.tracing import (
from cai.sdk.agents.tracing import (
Span,
Trace,
agent_span,
@ -16,9 +16,9 @@ from agents.tracing import (
handoff_span,
trace,
)
from agents.tracing.spans import SpanError
from cai.sdk.agents.tracing.spans import SpanError
from .testing_processor import (
from tests.testing_processor import (
SPAN_PROCESSOR_TESTING,
assert_no_traces,
fetch_events,

View File

@ -7,7 +7,7 @@ import pytest
from inline_snapshot import snapshot
from typing_extensions import TypedDict
from agents import (
from cai.sdk.agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrail,
@ -19,15 +19,15 @@ from agents import (
TResponseInputItem,
)
from .fake_model import FakeModel
from .test_responses import (
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,
get_handoff_tool_call,
get_text_message,
)
from .testing_processor import fetch_normalized_spans
from tests.testing_processor import fetch_normalized_spans
@pytest.mark.asyncio

View File

@ -8,7 +8,7 @@ import pytest
from inline_snapshot import snapshot
from typing_extensions import TypedDict
from agents import (
from cai.sdk.agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrail,
@ -22,15 +22,15 @@ from agents import (
TResponseInputItem,
)
from .fake_model import FakeModel
from .test_responses import (
from tests.fake_model import FakeModel
from tests.core.test_responses import (
get_final_output_message,
get_function_tool,
get_function_tool_call,
get_handoff_tool_call,
get_text_message,
)
from .testing_processor import fetch_normalized_spans
from tests.testing_processor import fetch_normalized_spans
@pytest.mark.asyncio

View File

@ -7,7 +7,7 @@ import numpy as np
import numpy.typing as npt
try:
from agents.voice import (
from cai.sdk.agents.voice import (
AudioInput,
StreamedAudioInput,
StreamedTranscriptionSession,

View File

@ -1,5 +1,5 @@
try:
from agents.voice import StreamedAudioResult
from cai.sdk.agents.voice import StreamedAudioResult
except ImportError:
pass

View File

@ -5,9 +5,9 @@ import numpy as np
import pytest
try:
from agents import UserError
from agents.voice import AudioInput, StreamedAudioInput
from agents.voice.input import DEFAULT_SAMPLE_RATE, _buffer_to_audio_file
from cai.sdk.agents import UserError
from cai.sdk.agents.voice import AudioInput, StreamedAudioInput
from cai.sdk.agents.voice.input import DEFAULT_SAMPLE_RATE, _buffer_to_audio_file
except ImportError:
pass

View File

@ -9,11 +9,11 @@ import numpy as np
import pytest
try:
from agents.voice import OpenAISTTTranscriptionSession, StreamedAudioInput, STTModelSettings
from agents.voice.exceptions import STTWebsocketConnectionError
from agents.voice.models.openai_stt import EVENT_INACTIVITY_TIMEOUT
from cai.sdk.agents.voice import OpenAISTTTranscriptionSession, StreamedAudioInput, STTModelSettings
from cai.sdk.agents.voice.exceptions import STTWebsocketConnectionError
from cai.sdk.agents.voice.models.openai_stt import EVENT_INACTIVITY_TIMEOUT
from .fake_models import FakeStreamedAudioInput
from tests.voice.fake_models import FakeStreamedAudioInput
except ImportError:
pass

View File

@ -6,7 +6,7 @@ from typing import Any
import pytest
try:
from agents.voice import OpenAITTSModel, TTSModelSettings
from cai.sdk.agents.voice import OpenAITTSModel, TTSModelSettings
except ImportError:
pass

View File

@ -5,10 +5,10 @@ import numpy.typing as npt
import pytest
try:
from agents.voice import AudioInput, TTSModelSettings, VoicePipeline, VoicePipelineConfig
from cai.sdk.agents.voice import AudioInput, TTSModelSettings, VoicePipeline, VoicePipelineConfig
from .fake_models import FakeStreamedAudioInput, FakeSTT, FakeTTS, FakeWorkflow
from .helpers import extract_events
from tests.voice.fake_models import FakeStreamedAudioInput, FakeSTT, FakeTTS, FakeWorkflow
from tests.mcp.helpers import extract_events
except ImportError:
pass

View File

@ -8,10 +8,10 @@ from inline_snapshot import snapshot
from openai.types.responses import ResponseCompletedEvent
from openai.types.responses.response_text_delta_event import ResponseTextDeltaEvent
from agents import Agent, Model, ModelSettings, ModelTracing, Tool
from agents.agent_output import AgentOutputSchema
from agents.handoffs import Handoff
from agents.items import (
from cai.sdk.agents import Agent, Model, ModelSettings, ModelTracing, Tool
from cai.sdk.agents.agent_output import AgentOutputSchema
from cai.sdk.agents.handoffs import Handoff
from cai.sdk.agents.items import (
ModelResponse,
TResponseInputItem,
TResponseOutputItem,
@ -19,10 +19,10 @@ from agents.items import (
)
try:
from agents.voice import SingleAgentVoiceWorkflow
from cai.sdk.agents.voice import SingleAgentVoiceWorkflow
from ..fake_model import get_response_obj
from ..test_responses import get_function_tool, get_function_tool_call, get_text_message
from tests.fake_model import get_response_obj
from tests.core.test_responses import get_function_tool, get_function_tool_call, get_text_message
except ImportError:
pass