From e59e3d10d8ad39e77d0628c8d2c65969aa054092 Mon Sep 17 00:00:00 2001 From: rodrigobr-msft Date: Wed, 26 Nov 2025 17:14:36 -0600 Subject: [PATCH 1/3] Getting package version from file when building packages (#261) * Writing version to file and reading it when building * Fixing issue * Removed unnecessary declaration * Specifying encoding --- .azdo/ci-pr.yaml | 5 +++++ libraries/microsoft-agents-activity/setup.py | 10 ++++++++-- .../microsoft-agents-authentication-msal/setup.py | 10 ++++++++-- .../microsoft-agents-copilotstudio-client/setup.py | 10 ++++++++-- libraries/microsoft-agents-hosting-aiohttp/setup.py | 10 ++++++++-- libraries/microsoft-agents-hosting-core/setup.py | 10 ++++++++-- libraries/microsoft-agents-hosting-fastapi/setup.py | 10 ++++++++-- libraries/microsoft-agents-hosting-teams/setup.py | 10 ++++++++-- libraries/microsoft-agents-storage-blob/setup.py | 10 ++++++++-- libraries/microsoft-agents-storage-cosmos/setup.py | 10 ++++++++-- 10 files changed, 77 insertions(+), 18 deletions(-) diff --git a/.azdo/ci-pr.yaml b/.azdo/ci-pr.yaml index cf6e2ff8..ad3b3112 100644 --- a/.azdo/ci-pr.yaml +++ b/.azdo/ci-pr.yaml @@ -52,6 +52,11 @@ steps: - script: | mkdir -p dist + for dir in libraries/*; do + if [ -f "$dir/pyproject.toml" ]; then + echo $(PackageVersion) > "$dir/VERSION.txt" + fi + done for dir in libraries/*; do if [ -f "$dir/pyproject.toml" ]; then (cd "$dir" && python -m build --outdir ../../dist) diff --git a/libraries/microsoft-agents-activity/setup.py b/libraries/microsoft-agents-activity/setup.py index 9b6de9af..c46ba05d 100644 --- a/libraries/microsoft-agents-activity/setup.py +++ b/libraries/microsoft-agents-activity/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-authentication-msal/setup.py b/libraries/microsoft-agents-authentication-msal/setup.py index 67315bcf..6b4e9860 100644 --- a/libraries/microsoft-agents-authentication-msal/setup.py +++ b/libraries/microsoft-agents-authentication-msal/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-copilotstudio-client/setup.py b/libraries/microsoft-agents-copilotstudio-client/setup.py index 41a7da0d..53449889 100644 --- a/libraries/microsoft-agents-copilotstudio-client/setup.py +++ b/libraries/microsoft-agents-copilotstudio-client/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-hosting-aiohttp/setup.py b/libraries/microsoft-agents-hosting-aiohttp/setup.py index 426735ba..f7a4e1bb 100644 --- a/libraries/microsoft-agents-hosting-aiohttp/setup.py +++ b/libraries/microsoft-agents-hosting-aiohttp/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-hosting-core/setup.py b/libraries/microsoft-agents-hosting-core/setup.py index e7604116..b1da90cf 100644 --- a/libraries/microsoft-agents-hosting-core/setup.py +++ b/libraries/microsoft-agents-hosting-core/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-hosting-fastapi/setup.py b/libraries/microsoft-agents-hosting-fastapi/setup.py index cfcb460b..a8e569b4 100644 --- a/libraries/microsoft-agents-hosting-fastapi/setup.py +++ b/libraries/microsoft-agents-hosting-fastapi/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-hosting-teams/setup.py b/libraries/microsoft-agents-hosting-teams/setup.py index 426735ba..f7a4e1bb 100644 --- a/libraries/microsoft-agents-hosting-teams/setup.py +++ b/libraries/microsoft-agents-hosting-teams/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-storage-blob/setup.py b/libraries/microsoft-agents-storage-blob/setup.py index d38c25bb..8fba7f42 100644 --- a/libraries/microsoft-agents-storage-blob/setup.py +++ b/libraries/microsoft-agents-storage-blob/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, diff --git a/libraries/microsoft-agents-storage-cosmos/setup.py b/libraries/microsoft-agents-storage-cosmos/setup.py index 8f09a0d2..f51a394f 100644 --- a/libraries/microsoft-agents-storage-cosmos/setup.py +++ b/libraries/microsoft-agents-storage-cosmos/setup.py @@ -1,7 +1,13 @@ -from os import environ +from os import environ, path from setuptools import setup -package_version = environ.get("PackageVersion", "0.0.0") +# Try to read from VERSION.txt file first, fall back to environment variable +version_file = path.join(path.dirname(__file__), "VERSION.txt") +if path.exists(version_file): + with open(version_file, "r", encoding="utf-8") as f: + package_version = f.read().strip() +else: + package_version = environ.get("PackageVersion", "0.0.0") setup( version=package_version, From 516b5fe280ad30f886218f549186706a6144c859 Mon Sep 17 00:00:00 2001 From: rodrigobr-msft Date: Mon, 1 Dec 2025 14:31:03 -0600 Subject: [PATCH 2/3] Adding MANIFEST.in file to include package version files in builds (#263) * Writing version to file and reading it when building * Fixing issue * Removed unnecessary declaration * Specifying encoding * Adding MANIFEST.in files to include VERSION.txt --- libraries/microsoft-agents-activity/MANIFEST.in | 1 + libraries/microsoft-agents-authentication-msal/MANIFEST.in | 1 + libraries/microsoft-agents-copilotstudio-client/MANIFEST.in | 1 + libraries/microsoft-agents-hosting-aiohttp/MANIFEST.in | 1 + libraries/microsoft-agents-hosting-core/MANIFEST.in | 1 + libraries/microsoft-agents-hosting-fastapi/MANIFEST.in | 1 + libraries/microsoft-agents-hosting-teams/MANIFEST.in | 1 + libraries/microsoft-agents-storage-blob/MANIFEST.in | 1 + libraries/microsoft-agents-storage-cosmos/MANIFEST.in | 1 + 9 files changed, 9 insertions(+) create mode 100644 libraries/microsoft-agents-activity/MANIFEST.in create mode 100644 libraries/microsoft-agents-authentication-msal/MANIFEST.in create mode 100644 libraries/microsoft-agents-copilotstudio-client/MANIFEST.in create mode 100644 libraries/microsoft-agents-hosting-aiohttp/MANIFEST.in create mode 100644 libraries/microsoft-agents-hosting-core/MANIFEST.in create mode 100644 libraries/microsoft-agents-hosting-fastapi/MANIFEST.in create mode 100644 libraries/microsoft-agents-hosting-teams/MANIFEST.in create mode 100644 libraries/microsoft-agents-storage-blob/MANIFEST.in create mode 100644 libraries/microsoft-agents-storage-cosmos/MANIFEST.in diff --git a/libraries/microsoft-agents-activity/MANIFEST.in b/libraries/microsoft-agents-activity/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-activity/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-authentication-msal/MANIFEST.in b/libraries/microsoft-agents-authentication-msal/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-authentication-msal/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-copilotstudio-client/MANIFEST.in b/libraries/microsoft-agents-copilotstudio-client/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-copilotstudio-client/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-hosting-aiohttp/MANIFEST.in b/libraries/microsoft-agents-hosting-aiohttp/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-hosting-aiohttp/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-hosting-core/MANIFEST.in b/libraries/microsoft-agents-hosting-core/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-hosting-core/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-hosting-fastapi/MANIFEST.in b/libraries/microsoft-agents-hosting-fastapi/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-hosting-fastapi/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-hosting-teams/MANIFEST.in b/libraries/microsoft-agents-hosting-teams/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-hosting-teams/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-storage-blob/MANIFEST.in b/libraries/microsoft-agents-storage-blob/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-storage-blob/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file diff --git a/libraries/microsoft-agents-storage-cosmos/MANIFEST.in b/libraries/microsoft-agents-storage-cosmos/MANIFEST.in new file mode 100644 index 00000000..43a71d9e --- /dev/null +++ b/libraries/microsoft-agents-storage-cosmos/MANIFEST.in @@ -0,0 +1 @@ +include VERSION.txt \ No newline at end of file From 284f3773159f6ad4b9f9253b371be99c988694ad Mon Sep 17 00:00:00 2001 From: rodrigobr-msft Date: Mon, 1 Dec 2025 14:35:30 -0600 Subject: [PATCH 3/3] Fixing _sign_in_state serialization/deserialization (#264) * Fixing _sign_in_state (de)serialization * Reformatting --------- Co-authored-by: Chris Mullins --- .../hosting/core/app/oauth/_sign_in_state.py | 22 +++------- tests/hosting_core/app/_oauth/_common.py | 8 ++-- .../app/_oauth/test_sign_in_state.py | 43 +++++++++++++++++++ 3 files changed, 55 insertions(+), 18 deletions(-) create mode 100644 tests/hosting_core/app/_oauth/test_sign_in_state.py diff --git a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/_sign_in_state.py b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/_sign_in_state.py index ddd22d90..bd16530a 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/_sign_in_state.py +++ b/libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/app/oauth/_sign_in_state.py @@ -7,35 +7,27 @@ from typing import Optional +from pydantic import BaseModel + from microsoft_agents.activity import Activity from ...storage._type_aliases import JSON from ...storage import StoreItem -class _SignInState(StoreItem): +class _SignInState(BaseModel, StoreItem): """Store item for sign-in state, including tokens and continuation activity. Used to cache tokens and keep track of activities during single and multi-turn sign-in flows. """ - def __init__( - self, - active_handler_id: str, - continuation_activity: Optional[Activity] = None, - ) -> None: - self.active_handler_id = active_handler_id - self.continuation_activity = continuation_activity + active_handler_id: str + continuation_activity: Optional[Activity] = None def store_item_to_json(self) -> JSON: - return { - "active_handler_id": self.active_handler_id, - "continuation_activity": self.continuation_activity, - } + return self.model_dump(mode="json", exclude_unset=True, by_alias=True) @staticmethod def from_json_to_store_item(json_data: JSON) -> _SignInState: - return _SignInState( - json_data["active_handler_id"], json_data.get("continuation_activity") - ) + return _SignInState.model_validate(json_data) diff --git a/tests/hosting_core/app/_oauth/_common.py b/tests/hosting_core/app/_oauth/_common.py index c2a6d2f0..4d3fea34 100644 --- a/tests/hosting_core/app/_oauth/_common.py +++ b/tests/hosting_core/app/_oauth/_common.py @@ -29,9 +29,11 @@ def create_testing_TurnContext( turn_context = mocker.Mock() if not activity: - turn_context.activity.channel_id = channel_id - turn_context.activity.from_property.id = user_id - turn_context.activity.type = ActivityTypes.message + turn_context.activity = Activity( + type=ActivityTypes.message, + channel_id=channel_id, + from_property={"id": user_id}, + ) else: turn_context.activity = activity turn_context.adapter.USER_TOKEN_CLIENT_KEY = "__user_token_client" diff --git a/tests/hosting_core/app/_oauth/test_sign_in_state.py b/tests/hosting_core/app/_oauth/test_sign_in_state.py new file mode 100644 index 00000000..d3bce6ec --- /dev/null +++ b/tests/hosting_core/app/_oauth/test_sign_in_state.py @@ -0,0 +1,43 @@ +import json + +from microsoft_agents.activity import Activity +from microsoft_agents.hosting.core.app.oauth._sign_in_state import _SignInState + + +def test_sign_in_state_serialization_deserialization(tmp_path): + original_state = _SignInState( + active_handler_id="handler_123", + continuation_activity=Activity( + type="message", + id="activity_456", + timestamp="2024-01-01T12:00:00Z", + service_url="https://service.url", + channel_id="channel_789", + from_property={"id": "user_1"}, + conversation={"id": "conv_1"}, + recipient={"id": "bot_1"}, + text="Hello, World!", + ), + ) + + # Serialize to JSON + json_data = original_state.store_item_to_json() + + # Deserialize back to _SignInState + deserialized_state = _SignInState.from_json_to_store_item(json_data) + + # Assert equality + assert deserialized_state.active_handler_id == original_state.active_handler_id + assert ( + deserialized_state.continuation_activity == original_state.continuation_activity + ) + + with open(tmp_path / "sign_in_state.json", "w") as f: + json.dump(json_data, f) + + with open(tmp_path / "sign_in_state.json", "r") as f: + loaded_json_data = json.load(f) + + loaded_state = _SignInState.from_json_to_store_item(loaded_json_data) + assert loaded_state.active_handler_id == original_state.active_handler_id + assert loaded_state.continuation_activity == original_state.continuation_activity