mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Add type annotations for AgentRunEvent and AgentRunUpdateEvent data attributes (#2589)
* Add type annotations for AgentRunEvent and AgentRunUpdateEvent data attributes * Fix unnecessary cast after typing improvement * Mcp pkg update introduced type change. Fix it. * update opentelemetry deps to 1.39.0 and use LogRecordExporter for type compatibility
This commit is contained in:
committed by
GitHub
Unverified
parent
9c2e800189
commit
a597a925cb
@@ -244,7 +244,7 @@ class WorkflowAgent(BaseAgent):
|
||||
case AgentRunUpdateEvent(data=update):
|
||||
# Direct pass-through of update in an agent streaming event
|
||||
if update:
|
||||
return cast(AgentRunResponseUpdate, update)
|
||||
return update
|
||||
return None
|
||||
|
||||
case RequestInfoEvent(request_id=request_id):
|
||||
|
||||
@@ -367,6 +367,8 @@ class ExecutorFailedEvent(ExecutorEvent):
|
||||
class AgentRunUpdateEvent(ExecutorEvent):
|
||||
"""Event triggered when an agent is streaming messages."""
|
||||
|
||||
data: AgentRunResponseUpdate | None
|
||||
|
||||
def __init__(self, executor_id: str, data: AgentRunResponseUpdate | None = None):
|
||||
"""Initialize the agent streaming event."""
|
||||
super().__init__(executor_id, data)
|
||||
@@ -379,6 +381,8 @@ class AgentRunUpdateEvent(ExecutorEvent):
|
||||
class AgentRunEvent(ExecutorEvent):
|
||||
"""Event triggered when an agent run is completed."""
|
||||
|
||||
data: AgentRunResponse | None
|
||||
|
||||
def __init__(self, executor_id: str, data: AgentRunResponse | None = None):
|
||||
"""Initialize the agent run event."""
|
||||
super().__init__(executor_id, data)
|
||||
|
||||
@@ -20,7 +20,7 @@ from .exceptions import AgentInitializationError, ChatClientInitializationError
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from azure.core.credentials import TokenCredential
|
||||
from opentelemetry.sdk._logs._internal.export import LogExporter
|
||||
from opentelemetry.sdk._logs._internal.export import LogRecordExporter
|
||||
from opentelemetry.sdk.metrics.export import MetricExporter
|
||||
from opentelemetry.sdk.resources import Resource
|
||||
from opentelemetry.sdk.trace.export import SpanExporter
|
||||
@@ -259,13 +259,13 @@ FINISH_REASON_MAP = {
|
||||
# region Telemetry utils
|
||||
|
||||
|
||||
def _get_otlp_exporters(endpoints: list[str]) -> list["LogExporter | SpanExporter | MetricExporter"]:
|
||||
def _get_otlp_exporters(endpoints: list[str]) -> list["LogRecordExporter | SpanExporter | MetricExporter"]:
|
||||
"""Create standard OTLP Exporters for the supplied endpoints."""
|
||||
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
|
||||
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
|
||||
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
||||
|
||||
exporters: list["LogExporter | SpanExporter | MetricExporter"] = []
|
||||
exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] = []
|
||||
|
||||
for endpoint in endpoints:
|
||||
exporters.append(OTLPLogExporter(endpoint=endpoint))
|
||||
@@ -277,7 +277,7 @@ def _get_otlp_exporters(endpoints: list[str]) -> list["LogExporter | SpanExporte
|
||||
def _get_azure_monitor_exporters(
|
||||
connection_strings: list[str],
|
||||
credential: "TokenCredential | None" = None,
|
||||
) -> list["LogExporter | SpanExporter | MetricExporter"]:
|
||||
) -> list["LogRecordExporter | SpanExporter | MetricExporter"]:
|
||||
"""Create Azure Monitor Exporters, based on the connection strings and optionally the credential."""
|
||||
try:
|
||||
from azure.monitor.opentelemetry.exporter import (
|
||||
@@ -291,7 +291,7 @@ def _get_azure_monitor_exporters(
|
||||
"Install it with: pip install azure-monitor-opentelemetry-exporter>=1.0.0b41"
|
||||
) from e
|
||||
|
||||
exporters: list["LogExporter | SpanExporter | MetricExporter"] = []
|
||||
exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] = []
|
||||
for conn_string in connection_strings:
|
||||
exporters.append(AzureMonitorLogExporter(connection_string=conn_string, credential=credential))
|
||||
exporters.append(AzureMonitorTraceExporter(connection_string=conn_string, credential=credential))
|
||||
@@ -303,7 +303,7 @@ def get_exporters(
|
||||
otlp_endpoints: list[str] | None = None,
|
||||
connection_strings: list[str] | None = None,
|
||||
credential: "TokenCredential | None" = None,
|
||||
) -> list["LogExporter | SpanExporter | MetricExporter"]:
|
||||
) -> list["LogRecordExporter | SpanExporter | MetricExporter"]:
|
||||
"""Add additional exporters to the existing configuration.
|
||||
|
||||
If you supply exporters, those will be added to the relevant providers directly.
|
||||
@@ -319,7 +319,7 @@ def get_exporters(
|
||||
connection_strings: A list of Azure Monitor connection strings. Default is None.
|
||||
credential: The credential to use for Azure Monitor Entra ID authentication. Default is None.
|
||||
"""
|
||||
new_exporters: list["LogExporter | SpanExporter | MetricExporter"] = []
|
||||
new_exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] = []
|
||||
if otlp_endpoints:
|
||||
new_exporters.extend(_get_otlp_exporters(endpoints=otlp_endpoints))
|
||||
|
||||
@@ -429,7 +429,7 @@ class ObservabilitySettings(AFBaseSettings):
|
||||
def _configure(
|
||||
self,
|
||||
credential: "TokenCredential | None" = None,
|
||||
additional_exporters: list["LogExporter | SpanExporter | MetricExporter"] | None = None,
|
||||
additional_exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] | None = None,
|
||||
) -> None:
|
||||
"""Configure application-wide observability based on the settings.
|
||||
|
||||
@@ -444,7 +444,7 @@ class ObservabilitySettings(AFBaseSettings):
|
||||
if not self.ENABLED or self._executed_setup:
|
||||
return
|
||||
|
||||
exporters: list["LogExporter | SpanExporter | MetricExporter"] = additional_exporters or []
|
||||
exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] = additional_exporters or []
|
||||
if self.otlp_endpoint:
|
||||
exporters.extend(
|
||||
_get_otlp_exporters(
|
||||
@@ -489,11 +489,11 @@ class ObservabilitySettings(AFBaseSettings):
|
||||
else [self.applicationinsights_connection_string]
|
||||
)
|
||||
|
||||
def _configure_providers(self, exporters: list["LogExporter | MetricExporter | SpanExporter"]) -> None:
|
||||
def _configure_providers(self, exporters: list["LogRecordExporter | MetricExporter | SpanExporter"]) -> None:
|
||||
"""Configure tracing, logging, events and metrics with the provided exporters."""
|
||||
from opentelemetry._logs import set_logger_provider
|
||||
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
|
||||
from opentelemetry.sdk._logs._internal.export import LogExporter
|
||||
from opentelemetry.sdk._logs._internal.export import LogRecordExporter
|
||||
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
|
||||
from opentelemetry.sdk.metrics import MeterProvider
|
||||
from opentelemetry.sdk.metrics.export import MetricExporter, PeriodicExportingMetricReader
|
||||
@@ -518,7 +518,7 @@ class ObservabilitySettings(AFBaseSettings):
|
||||
logger_provider = LoggerProvider(resource=self.resource)
|
||||
should_add_console_exporter = True
|
||||
for exporter in exporters:
|
||||
if isinstance(exporter, LogExporter):
|
||||
if isinstance(exporter, LogRecordExporter):
|
||||
logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
|
||||
should_add_console_exporter = False
|
||||
if should_add_console_exporter:
|
||||
@@ -667,7 +667,7 @@ def setup_observability(
|
||||
otlp_endpoint: str | list[str] | None = None,
|
||||
applicationinsights_connection_string: str | list[str] | None = None,
|
||||
credential: "TokenCredential | None" = None,
|
||||
exporters: list["LogExporter | SpanExporter | MetricExporter"] | None = None,
|
||||
exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] | None = None,
|
||||
vs_code_extension_port: int | None = None,
|
||||
) -> None:
|
||||
"""Setup observability for the application with OpenTelemetry.
|
||||
@@ -749,7 +749,7 @@ def setup_observability(
|
||||
OBSERVABILITY_SETTINGS.vs_code_extension_port = vs_code_extension_port
|
||||
|
||||
# Create exporters, after checking if they are already configured through the env.
|
||||
new_exporters: list["LogExporter | SpanExporter | MetricExporter"] = exporters or []
|
||||
new_exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] = exporters or []
|
||||
if otlp_endpoint:
|
||||
if isinstance(otlp_endpoint, str):
|
||||
otlp_endpoint = [otlp_endpoint]
|
||||
|
||||
@@ -28,9 +28,9 @@ dependencies = [
|
||||
"pydantic>=2,<3",
|
||||
"pydantic-settings>=2,<3",
|
||||
# telemetry
|
||||
"opentelemetry-api>=1.24",
|
||||
"opentelemetry-sdk>=1.24",
|
||||
"opentelemetry-exporter-otlp-proto-grpc>=1.36.0",
|
||||
"opentelemetry-api>=1.39.0",
|
||||
"opentelemetry-sdk>=1.39.0",
|
||||
"opentelemetry-exporter-otlp-proto-grpc>=1.39.0",
|
||||
"opentelemetry-semantic-conventions-ai>=0.4.13",
|
||||
# connectors and functions
|
||||
"openai>=1.99.0",
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
"""Tests for AgentRunEvent and AgentRunUpdateEvent type annotations."""
|
||||
|
||||
from agent_framework import AgentRunResponse, AgentRunResponseUpdate, ChatMessage, Role
|
||||
from agent_framework._workflows._events import AgentRunEvent, AgentRunUpdateEvent
|
||||
|
||||
|
||||
def test_agent_run_event_data_type() -> None:
|
||||
"""Verify AgentRunEvent.data is typed as AgentRunResponse | None."""
|
||||
response = AgentRunResponse(messages=[ChatMessage(role=Role.ASSISTANT, text="Hello")])
|
||||
event = AgentRunEvent(executor_id="test", data=response)
|
||||
|
||||
# This assignment should pass type checking without a cast
|
||||
data: AgentRunResponse | None = event.data
|
||||
assert data is not None
|
||||
assert data.text == "Hello"
|
||||
|
||||
|
||||
def test_agent_run_event_data_none() -> None:
|
||||
"""Verify AgentRunEvent.data can be None."""
|
||||
event = AgentRunEvent(executor_id="test")
|
||||
|
||||
data: AgentRunResponse | None = event.data
|
||||
assert data is None
|
||||
|
||||
|
||||
def test_agent_run_update_event_data_type() -> None:
|
||||
"""Verify AgentRunUpdateEvent.data is typed as AgentRunResponseUpdate | None."""
|
||||
update = AgentRunResponseUpdate()
|
||||
event = AgentRunUpdateEvent(executor_id="test", data=update)
|
||||
|
||||
# This assignment should pass type checking without a cast
|
||||
data: AgentRunResponseUpdate | None = event.data
|
||||
assert data is not None
|
||||
|
||||
|
||||
def test_agent_run_update_event_data_none() -> None:
|
||||
"""Verify AgentRunUpdateEvent.data can be None."""
|
||||
event = AgentRunUpdateEvent(executor_id="test")
|
||||
|
||||
data: AgentRunResponseUpdate | None = event.data
|
||||
assert data is None
|
||||
@@ -29,7 +29,7 @@ dependencies = [
|
||||
# GAIA benchmark module dependencies
|
||||
gaia = [
|
||||
"pydantic>=2.0.0",
|
||||
"opentelemetry-api>=1.24.0",
|
||||
"opentelemetry-api>=1.39.0",
|
||||
"tqdm>=4.60.0",
|
||||
"huggingface-hub>=0.20.0",
|
||||
"orjson>=3.8.0",
|
||||
|
||||
Reference in New Issue
Block a user