microsoft-agents-hosting-core 0.4.0.dev6__tar.gz → 0.4.0.dev10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/PKG-INFO +2 -2
  2. microsoft_agents_hosting_core-0.4.0.dev10/microsoft_agents/hosting/core/storage/__init__.py +24 -0
  3. microsoft_agents_hosting_core-0.4.0.dev10/microsoft_agents/hosting/core/storage/transcript_info.py +12 -0
  4. microsoft_agents_hosting_core-0.4.0.dev10/microsoft_agents/hosting/core/storage/transcript_logger.py +209 -0
  5. microsoft_agents_hosting_core-0.4.0.dev10/microsoft_agents/hosting/core/storage/transcript_memory_store.py +154 -0
  6. microsoft_agents_hosting_core-0.4.0.dev10/microsoft_agents/hosting/core/storage/transcript_store.py +52 -0
  7. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents_hosting_core.egg-info/PKG-INFO +2 -2
  8. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents_hosting_core.egg-info/SOURCES.txt +5 -14
  9. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents_hosting_core.egg-info/requires.txt +1 -1
  10. microsoft_agents_hosting_core-0.4.0.dev6/microsoft_agents/hosting/core/storage/__init__.py +0 -5
  11. microsoft_agents_hosting_core-0.4.0.dev6/microsoft_agents/hosting/core/storage/_storage_test_utils.py +0 -508
  12. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_activity_handler.py +0 -155
  13. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_agent_state.py +0 -513
  14. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_auth_configuration.py +0 -79
  15. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_authorization.py +0 -607
  16. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_error_handling.py +0 -61
  17. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_flow_state.py +0 -237
  18. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_flow_storage_client.py +0 -170
  19. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_memory_storage.py +0 -11
  20. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_oauth_flow.py +0 -604
  21. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_state.py +0 -270
  22. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_turn_context.py +0 -422
  23. microsoft_agents_hosting_core-0.4.0.dev6/tests/test_utils.py +0 -93
  24. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/__init__.py +0 -0
  25. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/activity_handler.py +0 -0
  26. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/agent.py +0 -0
  27. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/__init__.py +0 -0
  28. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/agent_application.py +0 -0
  29. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/app_error.py +0 -0
  30. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/app_options.py +0 -0
  31. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/input_file.py +0 -0
  32. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/oauth/__init__.py +0 -0
  33. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/oauth/auth_handler.py +0 -0
  34. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/oauth/authorization.py +0 -0
  35. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/query.py +0 -0
  36. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/route.py +0 -0
  37. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/state/__init__.py +0 -0
  38. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/state/conversation_state.py +0 -0
  39. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/state/state.py +0 -0
  40. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/state/temp_state.py +0 -0
  41. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/state/turn_state.py +0 -0
  42. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/app/typing_indicator.py +0 -0
  43. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/__init__.py +0 -0
  44. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/access_token_provider_base.py +0 -0
  45. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/agent_auth_configuration.py +0 -0
  46. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/anonymous_token_provider.py +0 -0
  47. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/auth_types.py +0 -0
  48. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/authentication_constants.py +0 -0
  49. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/claims_identity.py +0 -0
  50. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/connections.py +0 -0
  51. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/authorization/jwt_token_validator.py +0 -0
  52. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/card_factory.py +0 -0
  53. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/channel_adapter.py +0 -0
  54. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/channel_api_handler_protocol.py +0 -0
  55. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/channel_service_adapter.py +0 -0
  56. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/channel_service_client_factory_base.py +0 -0
  57. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/__init__.py +0 -0
  58. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/agent_conversation_reference.py +0 -0
  59. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/channel_factory_protocol.py +0 -0
  60. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/channel_host_protocol.py +0 -0
  61. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/channel_info_protocol.py +0 -0
  62. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/channel_protocol.py +0 -0
  63. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/channels_configuration.py +0 -0
  64. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/configuration_channel_host.py +0 -0
  65. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/conversation_constants.py +0 -0
  66. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/conversation_id_factory.py +0 -0
  67. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/conversation_id_factory_options.py +0 -0
  68. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/conversation_id_factory_protocol.py +0 -0
  69. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/http_agent_channel.py +0 -0
  70. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/client/http_agent_channel_factory.py +0 -0
  71. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/__init__.py +0 -0
  72. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/agent_sign_in_base.py +0 -0
  73. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/attachments_base.py +0 -0
  74. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/client/__init__.py +0 -0
  75. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/client/connector_client.py +0 -0
  76. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/client/user_token_client.py +0 -0
  77. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/connector_client_base.py +0 -0
  78. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/conversations_base.py +0 -0
  79. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/get_product_info.py +0 -0
  80. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/teams/__init__.py +0 -0
  81. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/teams/teams_connector_client.py +0 -0
  82. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/user_token_base.py +0 -0
  83. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/connector/user_token_client_base.py +0 -0
  84. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/message_factory.py +0 -0
  85. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/middleware_set.py +0 -0
  86. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/oauth/__init__.py +0 -0
  87. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/oauth/flow_state.py +0 -0
  88. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/oauth/flow_storage_client.py +0 -0
  89. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/oauth/oauth_flow.py +0 -0
  90. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/rest_channel_service_client_factory.py +0 -0
  91. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/state/__init__.py +0 -0
  92. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/state/agent_state.py +0 -0
  93. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/state/state_property_accessor.py +0 -0
  94. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/state/user_state.py +0 -0
  95. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/storage/_type_aliases.py +0 -0
  96. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/storage/error_handling.py +0 -0
  97. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/storage/memory_storage.py +0 -0
  98. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/storage/storage.py +0 -0
  99. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/storage/store_item.py +0 -0
  100. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents/hosting/core/turn_context.py +0 -0
  101. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents_hosting_core.egg-info/dependency_links.txt +0 -0
  102. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/microsoft_agents_hosting_core.egg-info/top_level.txt +0 -0
  103. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/pyproject.toml +0 -0
  104. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/setup.cfg +0 -0
  105. {microsoft_agents_hosting_core-0.4.0.dev6 → microsoft_agents_hosting_core-0.4.0.dev10}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microsoft-agents-hosting-core
3
- Version: 0.4.0.dev6
3
+ Version: 0.4.0.dev10
4
4
  Summary: Core library for Microsoft Agents
5
5
  Author: Microsoft Corporation
6
6
  Project-URL: Homepage, https://github.com/microsoft/Agents
@@ -8,7 +8,7 @@ Classifier: Programming Language :: Python :: 3
8
8
  Classifier: License :: OSI Approved :: MIT License
9
9
  Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.9
11
- Requires-Dist: microsoft-agents-activity==0.4.0.dev6
11
+ Requires-Dist: microsoft-agents-activity==0.4.0.dev10
12
12
  Requires-Dist: pyjwt>=2.10.1
13
13
  Requires-Dist: isodate>=0.6.1
14
14
  Requires-Dist: azure-core>=1.30.0
@@ -0,0 +1,24 @@
1
+ from .store_item import StoreItem
2
+ from .storage import Storage, AsyncStorageBase
3
+ from .memory_storage import MemoryStorage
4
+ from .transcript_info import TranscriptInfo
5
+ from .transcript_logger import (
6
+ TranscriptLogger,
7
+ ConsoleTranscriptLogger,
8
+ TranscriptLoggerMiddleware,
9
+ FileTranscriptLogger,
10
+ )
11
+ from .transcript_store import TranscriptStore
12
+
13
+ __all__ = [
14
+ "StoreItem",
15
+ "Storage",
16
+ "AsyncStorageBase",
17
+ "MemoryStorage",
18
+ "TranscriptInfo",
19
+ "TranscriptLogger",
20
+ "ConsoleTranscriptLogger",
21
+ "TranscriptLoggerMiddleware",
22
+ "TranscriptStore",
23
+ "FileTranscriptLogger",
24
+ ]
@@ -0,0 +1,12 @@
1
+ # Copyright (c) Microsoft Corporation. All rights reserved.
2
+ # Licensed under the MIT License.
3
+
4
+ from datetime import datetime, timezone
5
+ from dataclasses import dataclass
6
+
7
+
8
+ @dataclass
9
+ class TranscriptInfo:
10
+ channel_id: str = ""
11
+ conversation_id: str = ""
12
+ created_on: datetime = datetime.min.replace(tzinfo=timezone.utc)
@@ -0,0 +1,209 @@
1
+ # Copyright (c) Microsoft Corporation. All rights reserved.
2
+ # Licensed under the MIT License.
3
+ import copy
4
+ import random
5
+ import string
6
+ import json
7
+
8
+ from abc import ABC, abstractmethod
9
+ from datetime import datetime, timezone
10
+ from queue import Queue
11
+ from typing import Awaitable, Callable, List, Optional
12
+
13
+ from microsoft_agents.activity import Activity, ChannelAccount
14
+ from microsoft_agents.activity.activity import ConversationReference
15
+ from microsoft_agents.activity.activity_types import ActivityTypes
16
+ from microsoft_agents.activity.conversation_reference import ActivityEventNames
17
+ from microsoft_agents.hosting.core.middleware_set import Middleware, TurnContext
18
+
19
+
20
+ class TranscriptLogger(ABC):
21
+ @abstractmethod
22
+ async def log_activity(self, activity: Activity) -> None:
23
+ """
24
+ Asynchronously logs an activity.
25
+
26
+ :param activity: The activity to log.
27
+ """
28
+ pass
29
+
30
+
31
+ class ConsoleTranscriptLogger(TranscriptLogger):
32
+ """
33
+ ConsoleTranscriptLogger writes activities to Console output. This is a DEBUG class, intended for testing
34
+ and log tailing
35
+ """
36
+
37
+ async def log_activity(self, activity: Activity) -> None:
38
+ """Log an activity to the transcript.
39
+ :param activity:Activity being logged.
40
+ """
41
+ if not activity:
42
+ raise TypeError("Activity is required")
43
+
44
+ json_data = activity.model_dump_json()
45
+ parsed = json.loads(json_data)
46
+ print(json.dumps(parsed, indent=4))
47
+
48
+
49
+ class FileTranscriptLogger(TranscriptLogger):
50
+ """
51
+ A TranscriptLogger implementation that appends each activity as JSON to a file. This class appends
52
+ each activity to the given file using basic formatting. This is a DEBUG class, intended for testing
53
+ and log tailing.
54
+ """
55
+
56
+ def __init__(self, file_path: str, encoding: Optional[str] = "utf-8"):
57
+ """
58
+ Initializes the FileTranscriptLogger and opens the file for appending.
59
+
60
+ :param file_path: Path to the transcript log file.
61
+ :param encoding: File encoding (default: utf-8).
62
+ """
63
+ self.file_path = file_path
64
+ self.encoding = encoding
65
+
66
+ # Open file in append mode to ensure it exists
67
+ self._file = open(self.file_path, "a", encoding=self.encoding)
68
+
69
+ async def log_activity(self, activity: Activity) -> None:
70
+ """
71
+ Appends the given activity as a JSON line to the file. This method pretty-prints the JSON for readability, which makes
72
+ it non-performant. For production scenarios, consider a more efficient logging mechanism.
73
+
74
+ :param activity: The Activity object to log.
75
+ """
76
+ if not activity:
77
+ raise TypeError("Activity is required")
78
+
79
+ json_data = activity.model_dump_json()
80
+ parsed = json.loads(json_data)
81
+
82
+ self._file.write(json.dumps(parsed, indent=4))
83
+
84
+ # As this is a logging / debugging class, we want to ensure the data is written out immediately. This is another
85
+ # consideration that makes this class non-performant for production scenarios.
86
+ self._file.flush()
87
+
88
+ def __del__(self):
89
+ if hasattr(self, "_file"):
90
+ self._file.close()
91
+
92
+
93
+ class TranscriptLoggerMiddleware(Middleware):
94
+ """Logs incoming and outgoing activities to a TranscriptLogger."""
95
+
96
+ def __init__(self, logger: TranscriptLogger):
97
+ if not logger:
98
+ raise TypeError(
99
+ "TranscriptLoggerMiddleware requires a TranscriptLogger instance."
100
+ )
101
+
102
+ self.logger = logger
103
+
104
+ async def on_turn(
105
+ self, context: TurnContext, logic: Callable[[TurnContext], Awaitable]
106
+ ):
107
+ """Initialization for middleware.
108
+ :param context: Context for the current turn of conversation with the user.
109
+ :param logic: Function to call at the end of the middleware chain.
110
+ """
111
+ transcript = Queue()
112
+ activity = context.activity
113
+ # Log incoming activity at beginning of turn
114
+ if activity:
115
+ if not activity.from_property:
116
+ activity.from_property = ChannelAccount()
117
+ if not activity.from_property.role:
118
+ activity.from_property.role = "user"
119
+
120
+ # We should not log ContinueConversation events used by skills to initialize the middleware.
121
+ if not (
122
+ context.activity.type == ActivityTypes.event
123
+ and context.activity.name == ActivityEventNames.continue_conversation
124
+ ):
125
+ await self._queue_activity(transcript, copy.copy(activity))
126
+
127
+ # hook up onSend pipeline
128
+ # pylint: disable=unused-argument
129
+ async def send_activities_handler(
130
+ ctx: TurnContext,
131
+ activities: List[Activity],
132
+ next_send: Callable[[], Awaitable[None]],
133
+ ):
134
+ # Run full pipeline
135
+ responses = await next_send()
136
+ for index, activity in enumerate(activities):
137
+ cloned_activity = copy.copy(activity)
138
+ if responses and index < len(responses):
139
+ cloned_activity.id = responses[index].id
140
+
141
+ # For certain channels, a ResourceResponse with an id is not always sent to the bot.
142
+ # This fix uses the timestamp on the activity to populate its id for logging the transcript
143
+ # If there is no outgoing timestamp, the current time for the bot is used for the activity.id
144
+ if not cloned_activity.id:
145
+ alphanumeric = string.ascii_lowercase + string.digits
146
+ prefix = "g_" + "".join(
147
+ random.choice(alphanumeric) for i in range(5)
148
+ )
149
+ epoch = datetime.fromtimestamp(0, timezone.utc)
150
+ if cloned_activity.timestamp:
151
+ reference = cloned_activity.timestamp
152
+ else:
153
+ reference = datetime.now(timezone.utc)
154
+ delta = (reference - epoch).total_seconds() * 1000
155
+ cloned_activity.id = f"{prefix}{delta}"
156
+ await self._queue_activity(transcript, cloned_activity)
157
+ return responses
158
+
159
+ context.on_send_activities(send_activities_handler)
160
+
161
+ # hook up update activity pipeline
162
+ async def update_activity_handler(
163
+ ctx: TurnContext, activity: Activity, next_update: Callable[[], Awaitable]
164
+ ):
165
+ # Run full pipeline
166
+ response = await next_update()
167
+ update_activity = copy.copy(activity)
168
+ update_activity.type = ActivityTypes.message_update
169
+ await self._queue_activity(transcript, update_activity)
170
+ return response
171
+
172
+ context.on_update_activity(update_activity_handler)
173
+
174
+ # hook up delete activity pipeline
175
+ async def delete_activity_handler(
176
+ ctx: TurnContext,
177
+ reference: ConversationReference,
178
+ next_delete: Callable[[], Awaitable],
179
+ ):
180
+ # Run full pipeline
181
+ await next_delete()
182
+
183
+ delete_msg = Activity(
184
+ type=ActivityTypes.message_delete, id=reference.activity_id
185
+ )
186
+ deleted_activity: Activity = TurnContext.apply_conversation_reference(
187
+ delete_msg, reference, False
188
+ )
189
+ await self._queue_activity(transcript, deleted_activity)
190
+
191
+ context.on_delete_activity(delete_activity_handler)
192
+
193
+ if logic:
194
+ await logic()
195
+
196
+ # Flush transcript at end of turn
197
+ while not transcript.empty():
198
+ activity = transcript.get()
199
+ if activity is None:
200
+ break
201
+ await self.logger.log_activity(activity)
202
+ transcript.task_done()
203
+
204
+ async def _queue_activity(self, transcript: Queue, activity: Activity) -> None:
205
+ """Logs the activity.
206
+ :param transcript: transcript.
207
+ :param activity: Activity to log.
208
+ """
209
+ transcript.put(activity)
@@ -0,0 +1,154 @@
1
+ # Copyright (c) Microsoft Corporation. All rights reserved.
2
+ # Licensed under the MIT License.
3
+
4
+ from threading import Lock
5
+ from datetime import datetime, timezone
6
+ from typing import List
7
+ from .transcript_logger import TranscriptLogger
8
+ from .transcript_info import TranscriptInfo
9
+ from microsoft_agents.activity import Activity
10
+
11
+
12
+ class TranscriptMemoryStore(TranscriptLogger):
13
+ """
14
+ An in-memory implementation of the TranscriptLogger for storing and retrieving activities.
15
+
16
+ This class is thread-safe and stores all activities in a list. It supports logging activities,
17
+ retrieving activities for a specific channel and conversation, and filtering by timestamp.
18
+ Activities with a None timestamp are treated as the earliest possible datetime.
19
+
20
+ Note: This class is intended for testing and prototyping purposes only. It does not persist
21
+ data and is not suitable for production use. This store will also grow without bound over
22
+ time, making it especially unsuited for production use.
23
+ """
24
+
25
+ def __init__(self):
26
+ """
27
+ Initializes the TranscriptMemoryStore.
28
+ """
29
+ self._transcript = []
30
+ self.lock = Lock()
31
+
32
+ async def log_activity(self, activity: Activity) -> None:
33
+ """
34
+ Asynchronously logs an activity to the in-memory transcript.
35
+
36
+ :param activity: The Activity object to log. Must have a valid conversation and conversation id.
37
+ :raises ValueError: If activity, activity.conversation, or activity.conversation.id is None.
38
+ """
39
+ if not activity:
40
+ raise ValueError("Activity cannot be None")
41
+ if not activity.conversation:
42
+ raise ValueError("Activity.Conversation cannot be None")
43
+ if not activity.conversation.id:
44
+ raise ValueError("Activity.Conversation.id cannot be None")
45
+
46
+ with self.lock:
47
+ self._transcript.append(activity)
48
+
49
+ async def get_transcript_activities(
50
+ self,
51
+ channel_id: str,
52
+ conversation_id: str,
53
+ continuation_token: str = None,
54
+ start_date: datetime = datetime.min.replace(tzinfo=timezone.utc),
55
+ ) -> tuple[list[Activity], str]:
56
+ """
57
+ Retrieves activities for a given channel and conversation, optionally filtered by start_date.
58
+
59
+ :param channel_id: The channel ID to filter activities.
60
+ :param conversation_id: The conversation ID to filter activities.
61
+ :param continuation_token: (Unused) Token for pagination.
62
+ :param start_date: Only activities with timestamp >= start_date are returned. None timestamps are treated as datetime.min.
63
+ :return: A tuple containing the filtered list of Activity objects and a continuation token (always None).
64
+ :raises ValueError: If channel_id or conversation_id is None.
65
+ """
66
+ if not channel_id:
67
+ raise ValueError("channel_id cannot be None")
68
+ if not conversation_id:
69
+ raise ValueError("conversation_id cannot be None")
70
+
71
+ with self.lock:
72
+ # Get the activities that match on channel and conversation id
73
+ relevant_activities = [
74
+ a
75
+ for a in self._transcript
76
+ if a.channel_id == channel_id
77
+ and a.conversation
78
+ and a.conversation.id == conversation_id
79
+ ]
80
+ # sort these by timestamp, treating None as datetime.min
81
+ sorted_relevant_activities = sorted(
82
+ relevant_activities,
83
+ key=lambda a: (
84
+ a.timestamp
85
+ if a.timestamp is not None
86
+ else datetime.min.replace(tzinfo=timezone.utc)
87
+ ),
88
+ )
89
+ # grab the ones bigger than the requested start date, treating None as datetime.min
90
+ filtered_sorted_activities = [
91
+ a
92
+ for a in sorted_relevant_activities
93
+ if (
94
+ a.timestamp
95
+ if a.timestamp is not None
96
+ else datetime.min.replace(tzinfo=timezone.utc)
97
+ )
98
+ >= start_date
99
+ ]
100
+
101
+ return filtered_sorted_activities, None
102
+
103
+ async def delete_transcript(self, channel_id: str, conversation_id: str) -> None:
104
+ """
105
+ Deletes all activities for a given channel and conversation from the in-memory transcript.
106
+
107
+ :param channel_id: The channel ID whose transcript should be deleted.
108
+ :param conversation_id: The conversation ID whose transcript should be deleted.
109
+ :raises ValueError: If channel_id or conversation_id is None.
110
+ """
111
+ if not channel_id:
112
+ raise ValueError("channel_id cannot be None")
113
+ if not conversation_id:
114
+ raise ValueError("conversation_id cannot be None")
115
+
116
+ with self.lock:
117
+ self._transcript = [
118
+ a
119
+ for a in self._transcript
120
+ if not (
121
+ a.channel_id == channel_id
122
+ and a.conversation
123
+ and a.conversation.id == conversation_id
124
+ )
125
+ ]
126
+
127
+ async def list_transcripts(
128
+ self, channel_id: str, continuation_token: str = None
129
+ ) -> tuple[list[TranscriptInfo], str]:
130
+ """
131
+ Lists all transcripts (unique conversation IDs) for a given channel.
132
+
133
+ :param channel_id: The channel ID to list transcripts for.
134
+ :param continuation_token: (Unused) Token for pagination.
135
+ :return: A tuple containing a list of TranscriptInfo objects and a continuation token (always None).
136
+ :raises ValueError: If channel_id is None.
137
+ """
138
+ if not channel_id:
139
+ raise ValueError("channel_id cannot be None")
140
+
141
+ with self.lock:
142
+ relevant_activities = [
143
+ a for a in self._transcript if a.channel_id == channel_id
144
+ ]
145
+ conversations = set(
146
+ a.conversation.id
147
+ for a in relevant_activities
148
+ if a.conversation and a.conversation.id
149
+ )
150
+ transcript_infos = [
151
+ TranscriptInfo(channel_id=channel_id, conversation_id=conversation_id)
152
+ for conversation_id in conversations
153
+ ]
154
+ return transcript_infos, None
@@ -0,0 +1,52 @@
1
+ # Copyright (c) Microsoft Corporation. All rights reserved.
2
+ # Licensed under the MIT License.
3
+
4
+ from abc import ABC, abstractmethod
5
+ from datetime import datetime, timezone
6
+ from microsoft_agents.activity import Activity
7
+ from .transcript_info import TranscriptInfo
8
+ from .transcript_logger import TranscriptLogger
9
+
10
+
11
+ class TranscriptStore(TranscriptLogger):
12
+ @abstractmethod
13
+ async def get_transcript_activities(
14
+ self,
15
+ channel_id: str,
16
+ conversation_id: str,
17
+ continuation_token: str = None,
18
+ start_date: datetime = datetime.min.replace(tzinfo=timezone.utc),
19
+ ) -> tuple[list[Activity], str]:
20
+ """
21
+ Asynchronously retrieves activities from a transcript.
22
+
23
+ :param channel_id: The channel ID of the conversation.
24
+ :param conversation_id: The conversation ID.
25
+ :param continuation_token: (Optional) A token to continue retrieving activities from a specific point.
26
+ :param start_date: (Optional) The start date to filter activities.
27
+ :return: A tuple containing a list of activities and a continuation token.
28
+ """
29
+ pass
30
+
31
+ @abstractmethod
32
+ async def list_transcripts(
33
+ self, channel_id: str, continuation_token: str = None
34
+ ) -> tuple[list[TranscriptInfo, str]]:
35
+ """
36
+ Asynchronously lists transcripts for a given channel.
37
+
38
+ :param channel_id: The channel ID to list transcripts for.
39
+ :param continuation_token: (Optional) A token to continue listing transcripts from a specific point.
40
+ :return: A tuple containing a list of transcripts and a continuation token.
41
+ """
42
+ pass
43
+
44
+ @abstractmethod
45
+ async def delete_transcript(self, channel_id: str, conversation_id: str) -> None:
46
+ """
47
+ Asynchronously deletes a transcript.
48
+
49
+ :param channel_id: The channel ID of the conversation.
50
+ :param conversation_id: The conversation ID.
51
+ """
52
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microsoft-agents-hosting-core
3
- Version: 0.4.0.dev6
3
+ Version: 0.4.0.dev10
4
4
  Summary: Core library for Microsoft Agents
5
5
  Author: Microsoft Corporation
6
6
  Project-URL: Homepage, https://github.com/microsoft/Agents
@@ -8,7 +8,7 @@ Classifier: Programming Language :: Python :: 3
8
8
  Classifier: License :: OSI Approved :: MIT License
9
9
  Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.9
11
- Requires-Dist: microsoft-agents-activity==0.4.0.dev6
11
+ Requires-Dist: microsoft-agents-activity==0.4.0.dev10
12
12
  Requires-Dist: pyjwt>=2.10.1
13
13
  Requires-Dist: isodate>=0.6.1
14
14
  Requires-Dist: azure-core>=1.30.0
@@ -73,26 +73,17 @@ microsoft_agents/hosting/core/state/agent_state.py
73
73
  microsoft_agents/hosting/core/state/state_property_accessor.py
74
74
  microsoft_agents/hosting/core/state/user_state.py
75
75
  microsoft_agents/hosting/core/storage/__init__.py
76
- microsoft_agents/hosting/core/storage/_storage_test_utils.py
77
76
  microsoft_agents/hosting/core/storage/_type_aliases.py
78
77
  microsoft_agents/hosting/core/storage/error_handling.py
79
78
  microsoft_agents/hosting/core/storage/memory_storage.py
80
79
  microsoft_agents/hosting/core/storage/storage.py
81
80
  microsoft_agents/hosting/core/storage/store_item.py
81
+ microsoft_agents/hosting/core/storage/transcript_info.py
82
+ microsoft_agents/hosting/core/storage/transcript_logger.py
83
+ microsoft_agents/hosting/core/storage/transcript_memory_store.py
84
+ microsoft_agents/hosting/core/storage/transcript_store.py
82
85
  microsoft_agents_hosting_core.egg-info/PKG-INFO
83
86
  microsoft_agents_hosting_core.egg-info/SOURCES.txt
84
87
  microsoft_agents_hosting_core.egg-info/dependency_links.txt
85
88
  microsoft_agents_hosting_core.egg-info/requires.txt
86
- microsoft_agents_hosting_core.egg-info/top_level.txt
87
- tests/test_activity_handler.py
88
- tests/test_agent_state.py
89
- tests/test_auth_configuration.py
90
- tests/test_authorization.py
91
- tests/test_error_handling.py
92
- tests/test_flow_state.py
93
- tests/test_flow_storage_client.py
94
- tests/test_memory_storage.py
95
- tests/test_oauth_flow.py
96
- tests/test_state.py
97
- tests/test_turn_context.py
98
- tests/test_utils.py
89
+ microsoft_agents_hosting_core.egg-info/top_level.txt
@@ -1,4 +1,4 @@
1
- microsoft-agents-activity==0.4.0.dev6
1
+ microsoft-agents-activity==0.4.0.dev10
2
2
  pyjwt>=2.10.1
3
3
  isodate>=0.6.1
4
4
  azure-core>=1.30.0
@@ -1,5 +0,0 @@
1
- from .store_item import StoreItem
2
- from .storage import Storage, AsyncStorageBase
3
- from .memory_storage import MemoryStorage
4
-
5
- __all__ = ["StoreItem", "Storage", "AsyncStorageBase", "MemoryStorage"]