Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
"""

from __future__ import annotations
from importlib.metadata import version

import platform
import uuid
from typing import Any, Optional
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated

import jwt


class Utility:
_cached_version = None
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated

"""
Utility class providing common runtime operations for Agent 365.

Expand Down Expand Up @@ -80,3 +84,27 @@ def resolve_agent_identity(context: Any, auth_token: Optional[str]) -> str:

# Fallback to extracting App ID from the auth token
return Utility.get_app_id_from_token(auth_token)

@staticmethod
def get_user_agent_header(orchestrator: str = "") -> str:
Comment thread
JesuTerraz marked this conversation as resolved.
"""
Generates a User-Agent header string for SDK requests.

Args:
orchestrator: Optional orchestrator name to include in the User-Agent header.
Defaults to empty string if not provided.

Returns:
str: A formatted User-Agent header string containing SDK version, OS type,
Python version, and optional orchestrator information.
"""
if Utility._cached_version is None:
try:
Utility._cached_version = version("microsoft-agents-a365-runtime")
except Exception:
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
Utility._cached_version = "unknown"
Comment thread
JesuTerraz marked this conversation as resolved.

orchestrator_part = f"; {orchestrator}" if orchestrator else ""
os_type = platform.system()
python_version = platform.python_version()
return f"Agent365SDK/{Utility._cached_version} ({os_type}; Python {python_version}{orchestrator_part})"
27 changes: 27 additions & 0 deletions tests/runtime/test_utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import uuid
from unittest.mock import Mock
import platform
import re
Comment thread
JesuTerraz marked this conversation as resolved.

import jwt
import pytest
Expand Down Expand Up @@ -124,3 +126,28 @@ def test_resolve_agent_identity_exception_handling(create_test_jwt, mock_context

result = Utility.resolve_agent_identity(context, token)
assert result == "token-app-id"


def test_get_user_agent_header_default():
"""Test get_user_agent_header returns expected format with default orchestrator."""
os_type = platform.system()
py_version = platform.python_version()

result = Utility.get_user_agent_header()

# Regex for Agent365SDK/version (OS; Python/version)
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
pattern = rf"^Agent365SDK/.+ \({os_type}; Python {py_version}\)$"
assert re.match(pattern, result)


def test_get_user_agent_header_with_orchestrator():
"""Test get_user_agent_header includes orchestrator when provided."""
orchestrator = "TestOrchestrator"
os_type = platform.system()
py_version = platform.python_version()

result = Utility.get_user_agent_header(orchestrator)

# Regex for Agent365SDK/version (OS; Python/version; TestOrchestrator)
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
pattern = rf"^Agent365SDK/.+ \({os_type}; Python {py_version}; {orchestrator}\)$"
assert re.match(pattern, result)
Comment thread
JesuTerraz marked this conversation as resolved.
Loading