Skip to content
Open
Show file tree
Hide file tree
Changes from all 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 @@ -11,7 +11,7 @@
from collections import OrderedDict
from contextlib import asynccontextmanager
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, TypeVar
from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, TypeVar, cast

from azure.ai.agentserver.core.storage import FoundryStateStore, FoundryStorageEndpoint, FoundryStorageNotFoundError
from azure.core.credentials_async import AsyncTokenCredential
Expand Down Expand Up @@ -327,15 +327,17 @@ async def _read_item(
item = await store.get_item(_bounded_store_name(key))
if item is None or target_cls is None:
return None, None
return key, target_cls.from_json_to_store_item(item.value)
# ``StoreItem.from_json_to_store_item`` is annotated ``-> StoreItem`` upstream, so
# calling it through ``type[StoreItemT]`` does not narrow to the concrete subclass.
return key, cast(StoreItemT, target_cls.from_json_to_store_item(item.value))

async def _write_item(self, key: str, value: StoreItemT) -> None:
async def _write_item(self, key: str, value: StoreItem) -> None:
"""Create-or-replace one item, creating its backing store on first write.

:param key: The M365 storage key to write (also the store name).
:type key: str
:param value: The ``StoreItem`` to persist.
:type value: StoreItemT
:type value: ~microsoft_agents.hosting.core.storage.StoreItem
:return: None.
:rtype: None
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ def test_claims_authenticated_with_empty_bot_app_id_has_empty_claims():
but with no appid/audience entries."""
claims = bridge._build_outbound_claims(ClaimsIdentity, digital_worker=False, is_hosted=True, bot_app_id="")

assert claims.is_authenticated is True
# ``is_authenticated`` is deprecated upstream and now derives from the claim
# dict being non-empty, so assert on the authentication type instead.
assert claims.authentication_type == OutboundAuth.AUTH_TYPE_BEARER
assert claims.get_claim_value(OutboundAuth.CLAIM_APP_ID) is None
assert claims.get_claim_value(OutboundAuth.CLAIM_AUDIENCE) is None


# ---------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions sdk/agentserver/azure-ai-agentserver-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Release History

## 2.1.0b3 (Unreleased)

### Other Changes

- `FoundryStateStore.set_item()` and `create_item()` now accept any `Mapping[str, JSONValue]` for `value` instead of requiring a concrete `dict`. The payload is never mutated, only serialized, so the narrower `dict` requirement rejected valid callers (for example M365 `StoreItem.store_item_to_json()`, which returns a `MutableMapping`). Widening a parameter type is backward compatible for all existing callers.

## 2.1.0b2 (2026-08-18)

### Other Changes
Expand Down
4 changes: 2 additions & 2 deletions sdk/agentserver/azure-ai-agentserver-core/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ namespace azure.ai.agentserver.core.storage
async def create_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
*,
call_id: str | None = ...,
tags: Mapping[str, str] | None = ...
Expand Down Expand Up @@ -291,7 +291,7 @@ namespace azure.ai.agentserver.core.storage
async def set_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
*,
call_id: str | None = ...,
if_match: str | None = ...,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# ---------------------------------------------------------

VERSION = "2.1.0b2"
VERSION = "2.1.0b3"
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from ._state_serializer import (
DeletedStateStore,
DeletedStateStoreItem,
JSONObject,
JSONValue,
Order,
StateStore,
StateStoreItem,
Expand Down Expand Up @@ -139,7 +139,7 @@ def delete_store(self) -> DeletedStateStore:
def create_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
tags: Mapping[str, str] | None,
) -> StateStoreItemRef:
with self._lock:
Expand All @@ -159,7 +159,7 @@ def create_item(
def set_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
tags: Mapping[str, str] | None,
if_match: str | None,
) -> StateStoreItemRef:
Expand Down Expand Up @@ -296,7 +296,7 @@ def _write(self, document: dict[str, Any]) -> None:
def _new_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
tags: Mapping[str, str] | None,
) -> dict[str, Any]:
now = _now()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
_UNSET,
DeletedStateStore,
DeletedStateStoreItem,
JSONObject,
JSONValue,
StateStoreItemKeyPage,
Order,
StateStore,
Expand Down Expand Up @@ -374,7 +374,7 @@ async def update(
async def create_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
*,
tags: Mapping[str, str] | None = None,
call_id: str | None = None,
Expand All @@ -384,7 +384,7 @@ async def create_item(
:param key: The item key to create.
:type key: str
:param value: The item payload as a JSON object.
:type value: dict[str, any]
:type value: ~collections.abc.Mapping[str, any]
:keyword tags: Optional string labels stored with the item and used to
filter :meth:`list_keys`.
:paramtype tags: ~collections.abc.Mapping[str, str] or None
Expand Down Expand Up @@ -412,7 +412,7 @@ async def create_item(
async def set_item(
self,
key: str,
value: JSONObject,
value: Mapping[str, JSONValue],
*,
tags: Mapping[str, str] | None = None,
if_match: str | None = None,
Expand All @@ -424,7 +424,7 @@ async def set_item(
:param key: The item key to create or replace.
:type key: str
:param value: The item payload as a JSON object.
:type value: dict[str, any]
:type value: ~collections.abc.Mapping[str, any]
:keyword tags: Optional string labels stored with the item and used to
filter :meth:`list_keys`.
:paramtype tags: ~collections.abc.Mapping[str, str] or None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,13 @@ def serialize_store_update_request(description: str | None | object, tags: Mappi
return json.dumps(dict(request)).encode("utf-8")


def serialize_item_create_request(key: str, value: JSONObject, tags: Mapping[str, str] | None) -> bytes:
request = CreateItemRequest(key=key, value=value, tags=_to_wire_tags(tags))
def serialize_item_create_request(key: str, value: Mapping[str, JSONValue], tags: Mapping[str, str] | None) -> bytes:
request = CreateItemRequest(key=key, value=dict(value), tags=_to_wire_tags(tags))
return json.dumps(dict(request)).encode("utf-8")


def serialize_item_put_request(value: JSONObject, tags: Mapping[str, str] | None) -> bytes:
request = PutItemRequest(value=value, tags=_to_wire_tags(tags))
def serialize_item_put_request(value: Mapping[str, JSONValue], tags: Mapping[str, str] | None) -> bytes:
request = PutItemRequest(value=dict(value), tags=_to_wire_tags(tags))
return json.dumps(dict(request)).encode("utf-8")


Expand Down
Loading