mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
@@ -1,266 +0,0 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""Integration tests using the official OpenAI SDK to call DevUI."""
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
import http.client
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import pytest
|
||||
import uvicorn
|
||||
from openai import OpenAI
|
||||
|
||||
from agent_framework_devui import DevServer
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def devui_server() -> Generator[str, None, None]:
|
||||
"""Start a DevUI server for testing.
|
||||
|
||||
Yields:
|
||||
Base URL of the running server.
|
||||
"""
|
||||
# Get samples directory
|
||||
current_dir = Path(__file__).parent
|
||||
samples_dir = current_dir.parent.parent.parent / "samples" / "getting_started" / "devui"
|
||||
|
||||
if not samples_dir.exists():
|
||||
pytest.skip(f"Samples directory not found: {samples_dir}")
|
||||
|
||||
# Create and start server with port 0 to get a random available port
|
||||
server = DevServer(
|
||||
entities_dir=str(samples_dir.resolve()),
|
||||
host="127.0.0.1",
|
||||
port=0, # Use 0 to let OS assign a random available port
|
||||
ui_enabled=False,
|
||||
)
|
||||
|
||||
app = server.get_app()
|
||||
|
||||
server_config = uvicorn.Config(
|
||||
app=app,
|
||||
host="127.0.0.1",
|
||||
port=0, # Use 0 to let OS assign a random available port
|
||||
log_level="error",
|
||||
ws="none", # Disable websockets to avoid deprecation warnings
|
||||
)
|
||||
server_instance = uvicorn.Server(server_config)
|
||||
|
||||
def run_server() -> None:
|
||||
asyncio.run(server_instance.serve())
|
||||
|
||||
server_thread = threading.Thread(target=run_server, daemon=True)
|
||||
server_thread.start()
|
||||
|
||||
# Wait for server to start and get the actual port
|
||||
max_retries = 20
|
||||
actual_port = None
|
||||
for _ in range(max_retries):
|
||||
time.sleep(0.5)
|
||||
# Get the actual port from the server instance
|
||||
if hasattr(server_instance, "servers") and server_instance.servers:
|
||||
for srv in server_instance.servers:
|
||||
for socket in srv.sockets:
|
||||
actual_port = socket.getsockname()[1]
|
||||
break
|
||||
if actual_port:
|
||||
break
|
||||
|
||||
if actual_port:
|
||||
# Verify server is responding
|
||||
try:
|
||||
conn = http.client.HTTPConnection("127.0.0.1", actual_port, timeout=5)
|
||||
try:
|
||||
conn.request("GET", "/health")
|
||||
response = conn.getresponse()
|
||||
if response.status == 200:
|
||||
break
|
||||
finally:
|
||||
conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not actual_port:
|
||||
pytest.skip("Server failed to start - could not determine port")
|
||||
|
||||
yield f"http://127.0.0.1:{actual_port}"
|
||||
|
||||
# Cleanup
|
||||
with contextlib.suppress(Exception):
|
||||
server_instance.should_exit = True
|
||||
|
||||
|
||||
def test_openai_sdk_responses_create_with_entity_id(devui_server: str) -> None:
|
||||
"""Test using OpenAI SDK with entity_id in metadata (no model parameter)."""
|
||||
base_url = devui_server
|
||||
client = OpenAI(base_url=f"{base_url}/v1", api_key="not-needed")
|
||||
|
||||
# Get available entities - extract host and port from base_url
|
||||
parsed = urlparse(base_url)
|
||||
conn = http.client.HTTPConnection(parsed.hostname, parsed.port, timeout=10)
|
||||
try:
|
||||
conn.request("GET", "/v1/entities")
|
||||
response = conn.getresponse()
|
||||
entities = json.loads(response.read().decode("utf-8"))["entities"]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
assert len(entities) > 0, "No entities discovered"
|
||||
|
||||
# Find an agent entity
|
||||
agent = next((e for e in entities if e["type"] == "agent"), None)
|
||||
if not agent:
|
||||
pytest.skip("No agent entities found")
|
||||
|
||||
agent_id = agent["id"]
|
||||
|
||||
# Test non-streaming request with entity_id in metadata
|
||||
response = client.responses.create(
|
||||
metadata={"entity_id": agent_id},
|
||||
input="What is 2+2?",
|
||||
)
|
||||
|
||||
assert response.object == "response"
|
||||
assert len(response.output) > 0
|
||||
assert response.output[0].content is not None
|
||||
|
||||
|
||||
def test_openai_sdk_responses_create_streaming(devui_server: str) -> None:
|
||||
"""Test using OpenAI SDK with streaming enabled."""
|
||||
base_url = devui_server
|
||||
client = OpenAI(base_url=f"{base_url}/v1", api_key="not-needed")
|
||||
|
||||
# Get available entities - extract host and port from base_url
|
||||
parsed = urlparse(base_url)
|
||||
conn = http.client.HTTPConnection(parsed.hostname, parsed.port, timeout=10)
|
||||
try:
|
||||
conn.request("GET", "/v1/entities")
|
||||
response = conn.getresponse()
|
||||
entities = json.loads(response.read().decode("utf-8"))["entities"]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
assert len(entities) > 0, "No entities discovered"
|
||||
|
||||
# Find an agent entity
|
||||
agent = next((e for e in entities if e["type"] == "agent"), None)
|
||||
if not agent:
|
||||
pytest.skip("No agent entities found")
|
||||
|
||||
agent_id = agent["id"]
|
||||
|
||||
# Test streaming request
|
||||
stream = client.responses.create(
|
||||
metadata={"entity_id": agent_id},
|
||||
input="Count to 3",
|
||||
stream=True,
|
||||
)
|
||||
|
||||
events = []
|
||||
for event in stream:
|
||||
events.append(event)
|
||||
if len(events) >= 100: # Limit for safety
|
||||
break
|
||||
|
||||
assert len(events) > 0, "No events received from stream"
|
||||
|
||||
# Check that we got various event types
|
||||
event_types = {event.type for event in events}
|
||||
# Should have at least response.completed or some content events
|
||||
assert len(event_types) > 0
|
||||
|
||||
|
||||
def test_openai_sdk_with_conversations(devui_server: str) -> None:
|
||||
"""Test using OpenAI SDK with conversation continuity."""
|
||||
base_url = devui_server
|
||||
client = OpenAI(base_url=f"{base_url}/v1", api_key="not-needed")
|
||||
|
||||
# Get available entities - extract host and port from base_url
|
||||
parsed = urlparse(base_url)
|
||||
conn = http.client.HTTPConnection(parsed.hostname, parsed.port, timeout=10)
|
||||
try:
|
||||
conn.request("GET", "/v1/entities")
|
||||
response = conn.getresponse()
|
||||
entities = json.loads(response.read().decode("utf-8"))["entities"]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
assert len(entities) > 0, "No entities discovered"
|
||||
|
||||
# Find an agent entity
|
||||
agent = next((e for e in entities if e["type"] == "agent"), None)
|
||||
if not agent:
|
||||
pytest.skip("No agent entities found")
|
||||
|
||||
agent_id = agent["id"]
|
||||
|
||||
# Create a conversation
|
||||
conversation = client.conversations.create(metadata={"agent_id": agent_id})
|
||||
|
||||
assert conversation.id is not None
|
||||
|
||||
# First turn
|
||||
response1 = client.responses.create(
|
||||
metadata={"entity_id": agent_id},
|
||||
input="My name is Alice",
|
||||
conversation=conversation.id,
|
||||
)
|
||||
|
||||
assert response1.object == "response"
|
||||
assert len(response1.output) > 0
|
||||
|
||||
# Second turn - test conversation continuity
|
||||
response2 = client.responses.create(
|
||||
metadata={"entity_id": agent_id},
|
||||
input="What is my name?",
|
||||
conversation=conversation.id,
|
||||
)
|
||||
|
||||
assert response2.object == "response"
|
||||
assert len(response2.output) > 0
|
||||
# The agent should remember the name from the previous turn
|
||||
# Note: This may not work with all agents, so we just verify we got a response
|
||||
assert response2.output[0].content is not None
|
||||
|
||||
|
||||
def test_openai_sdk_with_model_and_entity_id(devui_server: str) -> None:
|
||||
"""Test that both model and entity_id can be specified together."""
|
||||
base_url = devui_server
|
||||
client = OpenAI(base_url=f"{base_url}/v1", api_key="not-needed")
|
||||
|
||||
# Get available entities - extract host and port from base_url
|
||||
parsed = urlparse(base_url)
|
||||
conn = http.client.HTTPConnection(parsed.hostname, parsed.port, timeout=10)
|
||||
try:
|
||||
conn.request("GET", "/v1/entities")
|
||||
response = conn.getresponse()
|
||||
entities = json.loads(response.read().decode("utf-8"))["entities"]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
assert len(entities) > 0, "No entities discovered"
|
||||
|
||||
# Find an agent entity
|
||||
agent = next((e for e in entities if e["type"] == "agent"), None)
|
||||
if not agent:
|
||||
pytest.skip("No agent entities found")
|
||||
|
||||
agent_id = agent["id"]
|
||||
|
||||
# Test with both model and entity_id - entity_id should be used for routing
|
||||
response = client.responses.create(
|
||||
metadata={"entity_id": agent_id},
|
||||
model="custom-model-name",
|
||||
input="Hello",
|
||||
)
|
||||
|
||||
assert response.object == "response"
|
||||
# The response model should reflect what was specified
|
||||
assert response.model == "custom-model-name"
|
||||
assert len(response.output) > 0
|
||||
Reference in New Issue
Block a user