We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SkillHandler doesn't return ResourceResponse when forwarding activities (Python)
See [parent](https://github.com/microsoft/botframework-sdk/issues/5919)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py`
Content:
```
1 # Copyright (c) Microsoft Corporation. All rights reserved.
2 # Licensed under the MIT License.
3 
4 from uuid import uuid4
5 
6 from botbuilder.core import Bot, BotAdapter, ChannelServiceHandler, TurnContext
7 from botbuilder.schema import (
8     Activity,
9     ActivityTypes,
10     ResourceResponse,
11     CallerIdConstants,
12 )
13 from botframework.connector.auth import (
14     AuthenticationConfiguration,
15     AuthenticationConstants,
16     ChannelProvider,
17     ClaimsIdentity,
18     CredentialProvider,
19     GovernmentConstants,
20     JwtTokenValidation,
21 )
22 from .skill_conversation_reference import SkillConversationReference
23 from .conversation_id_factory import ConversationIdFactoryBase
24 
25 
26 class SkillHandler(ChannelServiceHandler):
27 
28     SKILL_CONVERSATION_REFERENCE_KEY = (
29         "botbuilder.core.skills.SkillConversationReference"
30     )
31 
32     def __init__(
33         self,
34         adapter: BotAdapter,
35         bot: Bot,
36         conversation_id_factory: ConversationIdFactoryBase,
37         credential_provider: CredentialProvider,
38         auth_configuration: AuthenticationConfiguration,
39         channel_provider: ChannelProvider = None,
40         logger: object = None,
41     ):
42         super().__init__(credential_provider, auth_configuration, channel_provider)
43 
44         if not adapter:
45             raise TypeError("adapter can't be None")
46         if not bot:
47             raise TypeError("bot can't be None")
48         if not conversation_id_factory:
49             raise TypeError("conversation_id_factory can't be None")
50 
51         self._adapter = adapter
52         self._bot = bot
53         self._conversation_id_factory = conversation_id_factory
54         self._logger = logger
55 
56     async def on_send_to_conversation(
57         self, claims_identity: ClaimsIdentity, conversation_id: str, activity: Activity,
58     ) -> ResourceResponse:
59         """
60         send_to_conversation() API for Skill
61 
62         This method allows you to send an activity to the end of a conversation.
63 
64         This is slightly different from ReplyToActivity().
65         * SendToConversation(conversationId) - will append the activity to the end
66         of the conversation according to the timestamp or semantics of the channel.
67         * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply
68         to another activity, if the channel supports it. If the channel does not
69         support nested replies, ReplyToActivity falls back to SendToConversation.
70 
71         Use ReplyToActivity when replying to a specific activity in the
72         conversation.
73 
74         Use SendToConversation in all other cases.
75         :param claims_identity: Claims identity for the bot.
76         :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity`
77         :param conversation_id:The conversation ID.
78         :type conversation_id: str
79         :param activity: Activity to send.
80         :type activity: Activity
81         :return:
82         """
83         return await self._process_activity(
84             claims_identity, conversation_id, None, activity,
85         )
86 
87     async def on_reply_to_activity(
88         self,
89         claims_identity: ClaimsIdentity,
90         conversation_id: str,
91         activity_id: str,
92         activity: Activity,
93     ) -> ResourceResponse:
94         """
95         reply_to_activity() API for Skill.
96 
97         This method allows you to reply to an activity.
98 
99         This is slightly different from SendToConversation().
100         * SendToConversation(conversationId) - will append the activity to the end
101         of the conversation according to the timestamp or semantics of the channel.
102         * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply
103         to another activity, if the channel supports it. If the channel does not
104         support nested replies, ReplyToActivity falls back to SendToConversation.
105 
106         Use ReplyToActivity when replying to a specific activity in the
107         conversation.
108 
109         Use SendToConversation in all other cases.
110         :param claims_identity: Claims identity for the bot.
111         :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity`
112         :param conversation_id:The conversation ID.
113         :type conversation_id: str
114         :param activity: Activity to send.
115         :type activity: Activity
116         :return:
117         """
118         return await self._process_activity(
119             claims_identity, conversation_id, activity_id, activity,
120         )
121 
122     async def _process_activity(
123         self,
124         claims_identity: ClaimsIdentity,
125         conversation_id: str,
126         reply_to_activity_id: str,
127         activity: Activity,
128     ) -> ResourceResponse:
129         # Get the SkillsConversationReference
130         conversation_reference_result = await self._conversation_id_factory.get_conversation_reference(
131             conversation_id
132         )
133 
134         # ConversationIdFactory can return either a SkillConversationReference (the newer way),
135         # or a ConversationReference (the old way, but still here for compatibility).  If a
136         # ConversationReference is returned, build a new SkillConversationReference to simplify
137         # the remainder of this method.
138         skill_conversation_reference: SkillConversationReference = None
139         if isinstance(conversation_reference_result, SkillConversationReference):
140             skill_conversation_reference = conversation_reference_result
141         else:
142             skill_conversation_reference = SkillConversationReference(
143                 conversation_reference=conversation_reference_result,
144                 oauth_scope=(
145                     GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE
146                     if self._channel_provider and self._channel_provider.is_government()
147                     else AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE
148                 ),
149             )
150 
151         if not skill_conversation_reference:
152             raise KeyError("SkillConversationReference not found")
153 
154         async def callback(context: TurnContext):
155             context.turn_state[
156                 SkillHandler.SKILL_CONVERSATION_REFERENCE_KEY
157             ] = skill_conversation_reference
158 
159             TurnContext.apply_conversation_reference(
160                 activity, skill_conversation_reference.conversation_reference
161             )
162 
163             context.activity.id = reply_to_activity_id
164 
165             app_id = JwtTokenValidation.get_app_id_from_claims(claims_identity.claims)
166             context.activity.caller_id = (
167                 f"{CallerIdConstants.bot_to_bot_prefix}{app_id}"
168             )
169 
170             if activity.type == ActivityTypes.end_of_conversation:
171                 await self._conversation_id_factory.delete_conversation_reference(
172                     conversation_id
173                 )
174                 self._apply_eoc_to_turn_context_activity(context, activity)
175                 await self._bot.on_turn(context)
176             elif activity.type == ActivityTypes.event:
177                 self._apply_event_to_turn_context_activity(context, activity)
178                 await self._bot.on_turn(context)
179             else:
180                 await context.send_activity(activity)
181 
182         await self._adapter.continue_conversation(
183             skill_conversation_reference.conversation_reference,
184             callback,
185             claims_identity=claims_identity,
186             audience=skill_conversation_reference.oauth_scope,
187         )
188         return ResourceResponse(id=str(uuid4()))
189 
190     @staticmethod
191     def _apply_eoc_to_turn_context_activity(
192         context: TurnContext, end_of_conversation_activity: Activity
193     ):
194         context.activity.type = end_of_conversation_activity.type
195         context.activity.text = end_of_conversation_activity.text
196         context.activity.code = end_of_conversation_activity.code
197 
198         context.activity.reply_to_id = end_of_conversation_activity.reply_to_id
199         context.activity.value = end_of_conversation_activity.value
200         context.activity.entities = end_of_conversation_activity.entities
201         context.activity.locale = end_of_conversation_activity.locale
202         context.activity.local_timestamp = end_of_conversation_activity.local_timestamp
203         context.activity.timestamp = end_of_conversation_activity.timestamp
204         context.activity.channel_data = end_of_conversation_activity.channel_data
205         context.activity.additional_properties = (
206             end_of_conversation_activity.additional_properties
207         )
208 
209     @staticmethod
210     def _apply_event_to_turn_context_activity(
211         context: TurnContext, event_activity: Activity
212     ):
213         context.activity.type = event_activity.type
214         context.activity.name = event_activity.name
215         context.activity.value = event_activity.value
216         context.activity.relates_to = event_activity.relates_to
217 
218         context.activity.reply_to_id = event_activity.reply_to_id
219         context.activity.value = event_activity.value
220         context.activity.entities = event_activity.entities
221         context.activity.locale = event_activity.locale
222         context.activity.local_timestamp = event_activity.local_timestamp
223         context.activity.timestamp = event_activity.timestamp
224         context.activity.channel_data = event_activity.channel_data
225         context.activity.additional_properties = event_activity.additional_properties
226
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py b/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py
--- a/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py
+++ b/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py
@@ -151,7 +151,14 @@
         if not skill_conversation_reference:
             raise KeyError("SkillConversationReference not found")
 
+        if not skill_conversation_reference.conversation_reference:
+            raise KeyError("conversationReference not found")
+
+        # If an activity is sent, return the ResourceResponse
+        resource_response: ResourceResponse = None
+
         async def callback(context: TurnContext):
+            nonlocal resource_response
             context.turn_state[
                 SkillHandler.SKILL_CONVERSATION_REFERENCE_KEY
             ] = skill_conversation_reference
@@ -177,7 +184,7 @@
                 self._apply_event_to_turn_context_activity(context, activity)
                 await self._bot.on_turn(context)
             else:
-                await context.send_activity(activity)
+                resource_response = await context.send_activity(activity)
 
         await self._adapter.continue_conversation(
             skill_conversation_reference.conversation_reference,
@@ -185,7 +192,11 @@
             claims_identity=claims_identity,
             audience=skill_conversation_reference.oauth_scope,
         )
-        return ResourceResponse(id=str(uuid4()))
+
+        if not resource_response:
+            resource_response = ResourceResponse(id=str(uuid4()))
+
+        return resource_response
 
     @staticmethod
     def _apply_eoc_to_turn_context_activity(

{"golden_diff": "diff --git a/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py b/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py\n--- a/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py\n+++ b/libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py\n@@ -151,7 +151,14 @@\n         if not skill_conversation_reference:\n             raise KeyError(\"SkillConversationReference not found\")\n \n+        if not skill_conversation_reference.conversation_reference:\n+            raise KeyError(\"conversationReference not found\")\n+\n+        # If an activity is sent, return the ResourceResponse\n+        resource_response: ResourceResponse = None\n+\n         async def callback(context: TurnContext):\n+            nonlocal resource_response\n             context.turn_state[\n                 SkillHandler.SKILL_CONVERSATION_REFERENCE_KEY\n             ] = skill_conversation_reference\n@@ -177,7 +184,7 @@\n                 self._apply_event_to_turn_context_activity(context, activity)\n                 await self._bot.on_turn(context)\n             else:\n-                await context.send_activity(activity)\n+                resource_response = await context.send_activity(activity)\n \n         await self._adapter.continue_conversation(\n             skill_conversation_reference.conversation_reference,\n@@ -185,7 +192,11 @@\n             claims_identity=claims_identity,\n             audience=skill_conversation_reference.oauth_scope,\n         )\n-        return ResourceResponse(id=str(uuid4()))\n+\n+        if not resource_response:\n+            resource_response = ResourceResponse(id=str(uuid4()))\n+\n+        return resource_response\n \n     @staticmethod\n     def _apply_eoc_to_turn_context_activity(\n", "issue": "SkillHandler doesn't return ResourceResponse when forwarding activities (Python)\nSee [parent](https://github.com/microsoft/botframework-sdk/issues/5919)\n", "before_files": [{"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License.\n\nfrom uuid import uuid4\n\nfrom botbuilder.core import Bot, BotAdapter, ChannelServiceHandler, TurnContext\nfrom botbuilder.schema import (\n    Activity,\n    ActivityTypes,\n    ResourceResponse,\n    CallerIdConstants,\n)\nfrom botframework.connector.auth import (\n    AuthenticationConfiguration,\n    AuthenticationConstants,\n    ChannelProvider,\n    ClaimsIdentity,\n    CredentialProvider,\n    GovernmentConstants,\n    JwtTokenValidation,\n)\nfrom .skill_conversation_reference import SkillConversationReference\nfrom .conversation_id_factory import ConversationIdFactoryBase\n\n\nclass SkillHandler(ChannelServiceHandler):\n\n    SKILL_CONVERSATION_REFERENCE_KEY = (\n        \"botbuilder.core.skills.SkillConversationReference\"\n    )\n\n    def __init__(\n        self,\n        adapter: BotAdapter,\n        bot: Bot,\n        conversation_id_factory: ConversationIdFactoryBase,\n        credential_provider: CredentialProvider,\n        auth_configuration: AuthenticationConfiguration,\n        channel_provider: ChannelProvider = None,\n        logger: object = None,\n    ):\n        super().__init__(credential_provider, auth_configuration, channel_provider)\n\n        if not adapter:\n            raise TypeError(\"adapter can't be None\")\n        if not bot:\n            raise TypeError(\"bot can't be None\")\n        if not conversation_id_factory:\n            raise TypeError(\"conversation_id_factory can't be None\")\n\n        self._adapter = adapter\n        self._bot = bot\n        self._conversation_id_factory = conversation_id_factory\n        self._logger = logger\n\n    async def on_send_to_conversation(\n        self, claims_identity: ClaimsIdentity, conversation_id: str, activity: Activity,\n    ) -> ResourceResponse:\n        \"\"\"\n        send_to_conversation() API for Skill\n\n        This method allows you to send an activity to the end of a conversation.\n\n        This is slightly different from ReplyToActivity().\n        * SendToConversation(conversationId) - will append the activity to the end\n        of the conversation according to the timestamp or semantics of the channel.\n        * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply\n        to another activity, if the channel supports it. If the channel does not\n        support nested replies, ReplyToActivity falls back to SendToConversation.\n\n        Use ReplyToActivity when replying to a specific activity in the\n        conversation.\n\n        Use SendToConversation in all other cases.\n        :param claims_identity: Claims identity for the bot.\n        :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity`\n        :param conversation_id:The conversation ID.\n        :type conversation_id: str\n        :param activity: Activity to send.\n        :type activity: Activity\n        :return:\n        \"\"\"\n        return await self._process_activity(\n            claims_identity, conversation_id, None, activity,\n        )\n\n    async def on_reply_to_activity(\n        self,\n        claims_identity: ClaimsIdentity,\n        conversation_id: str,\n        activity_id: str,\n        activity: Activity,\n    ) -> ResourceResponse:\n        \"\"\"\n        reply_to_activity() API for Skill.\n\n        This method allows you to reply to an activity.\n\n        This is slightly different from SendToConversation().\n        * SendToConversation(conversationId) - will append the activity to the end\n        of the conversation according to the timestamp or semantics of the channel.\n        * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply\n        to another activity, if the channel supports it. If the channel does not\n        support nested replies, ReplyToActivity falls back to SendToConversation.\n\n        Use ReplyToActivity when replying to a specific activity in the\n        conversation.\n\n        Use SendToConversation in all other cases.\n        :param claims_identity: Claims identity for the bot.\n        :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity`\n        :param conversation_id:The conversation ID.\n        :type conversation_id: str\n        :param activity: Activity to send.\n        :type activity: Activity\n        :return:\n        \"\"\"\n        return await self._process_activity(\n            claims_identity, conversation_id, activity_id, activity,\n        )\n\n    async def _process_activity(\n        self,\n        claims_identity: ClaimsIdentity,\n        conversation_id: str,\n        reply_to_activity_id: str,\n        activity: Activity,\n    ) -> ResourceResponse:\n        # Get the SkillsConversationReference\n        conversation_reference_result = await self._conversation_id_factory.get_conversation_reference(\n            conversation_id\n        )\n\n        # ConversationIdFactory can return either a SkillConversationReference (the newer way),\n        # or a ConversationReference (the old way, but still here for compatibility).  If a\n        # ConversationReference is returned, build a new SkillConversationReference to simplify\n        # the remainder of this method.\n        skill_conversation_reference: SkillConversationReference = None\n        if isinstance(conversation_reference_result, SkillConversationReference):\n            skill_conversation_reference = conversation_reference_result\n        else:\n            skill_conversation_reference = SkillConversationReference(\n                conversation_reference=conversation_reference_result,\n                oauth_scope=(\n                    GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\n                    if self._channel_provider and self._channel_provider.is_government()\n                    else AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\n                ),\n            )\n\n        if not skill_conversation_reference:\n            raise KeyError(\"SkillConversationReference not found\")\n\n        async def callback(context: TurnContext):\n            context.turn_state[\n                SkillHandler.SKILL_CONVERSATION_REFERENCE_KEY\n            ] = skill_conversation_reference\n\n            TurnContext.apply_conversation_reference(\n                activity, skill_conversation_reference.conversation_reference\n            )\n\n            context.activity.id = reply_to_activity_id\n\n            app_id = JwtTokenValidation.get_app_id_from_claims(claims_identity.claims)\n            context.activity.caller_id = (\n                f\"{CallerIdConstants.bot_to_bot_prefix}{app_id}\"\n            )\n\n            if activity.type == ActivityTypes.end_of_conversation:\n                await self._conversation_id_factory.delete_conversation_reference(\n                    conversation_id\n                )\n                self._apply_eoc_to_turn_context_activity(context, activity)\n                await self._bot.on_turn(context)\n            elif activity.type == ActivityTypes.event:\n                self._apply_event_to_turn_context_activity(context, activity)\n                await self._bot.on_turn(context)\n            else:\n                await context.send_activity(activity)\n\n        await self._adapter.continue_conversation(\n            skill_conversation_reference.conversation_reference,\n            callback,\n            claims_identity=claims_identity,\n            audience=skill_conversation_reference.oauth_scope,\n        )\n        return ResourceResponse(id=str(uuid4()))\n\n    @staticmethod\n    def _apply_eoc_to_turn_context_activity(\n        context: TurnContext, end_of_conversation_activity: Activity\n    ):\n        context.activity.type = end_of_conversation_activity.type\n        context.activity.text = end_of_conversation_activity.text\n        context.activity.code = end_of_conversation_activity.code\n\n        context.activity.reply_to_id = end_of_conversation_activity.reply_to_id\n        context.activity.value = end_of_conversation_activity.value\n        context.activity.entities = end_of_conversation_activity.entities\n        context.activity.locale = end_of_conversation_activity.locale\n        context.activity.local_timestamp = end_of_conversation_activity.local_timestamp\n        context.activity.timestamp = end_of_conversation_activity.timestamp\n        context.activity.channel_data = end_of_conversation_activity.channel_data\n        context.activity.additional_properties = (\n            end_of_conversation_activity.additional_properties\n        )\n\n    @staticmethod\n    def _apply_event_to_turn_context_activity(\n        context: TurnContext, event_activity: Activity\n    ):\n        context.activity.type = event_activity.type\n        context.activity.name = event_activity.name\n        context.activity.value = event_activity.value\n        context.activity.relates_to = event_activity.relates_to\n\n        context.activity.reply_to_id = event_activity.reply_to_id\n        context.activity.value = event_activity.value\n        context.activity.entities = event_activity.entities\n        context.activity.locale = event_activity.locale\n        context.activity.local_timestamp = event_activity.local_timestamp\n        context.activity.timestamp = event_activity.timestamp\n        context.activity.channel_data = event_activity.channel_data\n        context.activity.additional_properties = event_activity.additional_properties\n", "path": "libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py"}], "after_files": [{"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License.\n\nfrom uuid import uuid4\n\nfrom botbuilder.core import Bot, BotAdapter, ChannelServiceHandler, TurnContext\nfrom botbuilder.schema import (\n    Activity,\n    ActivityTypes,\n    ResourceResponse,\n    CallerIdConstants,\n)\nfrom botframework.connector.auth import (\n    AuthenticationConfiguration,\n    AuthenticationConstants,\n    ChannelProvider,\n    ClaimsIdentity,\n    CredentialProvider,\n    GovernmentConstants,\n    JwtTokenValidation,\n)\nfrom .skill_conversation_reference import SkillConversationReference\nfrom .conversation_id_factory import ConversationIdFactoryBase\n\n\nclass SkillHandler(ChannelServiceHandler):\n\n    SKILL_CONVERSATION_REFERENCE_KEY = (\n        \"botbuilder.core.skills.SkillConversationReference\"\n    )\n\n    def __init__(\n        self,\n        adapter: BotAdapter,\n        bot: Bot,\n        conversation_id_factory: ConversationIdFactoryBase,\n        credential_provider: CredentialProvider,\n        auth_configuration: AuthenticationConfiguration,\n        channel_provider: ChannelProvider = None,\n        logger: object = None,\n    ):\n        super().__init__(credential_provider, auth_configuration, channel_provider)\n\n        if not adapter:\n            raise TypeError(\"adapter can't be None\")\n        if not bot:\n            raise TypeError(\"bot can't be None\")\n        if not conversation_id_factory:\n            raise TypeError(\"conversation_id_factory can't be None\")\n\n        self._adapter = adapter\n        self._bot = bot\n        self._conversation_id_factory = conversation_id_factory\n        self._logger = logger\n\n    async def on_send_to_conversation(\n        self, claims_identity: ClaimsIdentity, conversation_id: str, activity: Activity,\n    ) -> ResourceResponse:\n        \"\"\"\n        send_to_conversation() API for Skill\n\n        This method allows you to send an activity to the end of a conversation.\n\n        This is slightly different from ReplyToActivity().\n        * SendToConversation(conversationId) - will append the activity to the end\n        of the conversation according to the timestamp or semantics of the channel.\n        * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply\n        to another activity, if the channel supports it. If the channel does not\n        support nested replies, ReplyToActivity falls back to SendToConversation.\n\n        Use ReplyToActivity when replying to a specific activity in the\n        conversation.\n\n        Use SendToConversation in all other cases.\n        :param claims_identity: Claims identity for the bot.\n        :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity`\n        :param conversation_id:The conversation ID.\n        :type conversation_id: str\n        :param activity: Activity to send.\n        :type activity: Activity\n        :return:\n        \"\"\"\n        return await self._process_activity(\n            claims_identity, conversation_id, None, activity,\n        )\n\n    async def on_reply_to_activity(\n        self,\n        claims_identity: ClaimsIdentity,\n        conversation_id: str,\n        activity_id: str,\n        activity: Activity,\n    ) -> ResourceResponse:\n        \"\"\"\n        reply_to_activity() API for Skill.\n\n        This method allows you to reply to an activity.\n\n        This is slightly different from SendToConversation().\n        * SendToConversation(conversationId) - will append the activity to the end\n        of the conversation according to the timestamp or semantics of the channel.\n        * ReplyToActivity(conversationId,ActivityId) - adds the activity as a reply\n        to another activity, if the channel supports it. If the channel does not\n        support nested replies, ReplyToActivity falls back to SendToConversation.\n\n        Use ReplyToActivity when replying to a specific activity in the\n        conversation.\n\n        Use SendToConversation in all other cases.\n        :param claims_identity: Claims identity for the bot.\n        :type claims_identity: :class:`botframework.connector.auth.ClaimsIdentity`\n        :param conversation_id:The conversation ID.\n        :type conversation_id: str\n        :param activity: Activity to send.\n        :type activity: Activity\n        :return:\n        \"\"\"\n        return await self._process_activity(\n            claims_identity, conversation_id, activity_id, activity,\n        )\n\n    async def _process_activity(\n        self,\n        claims_identity: ClaimsIdentity,\n        conversation_id: str,\n        reply_to_activity_id: str,\n        activity: Activity,\n    ) -> ResourceResponse:\n        # Get the SkillsConversationReference\n        conversation_reference_result = await self._conversation_id_factory.get_conversation_reference(\n            conversation_id\n        )\n\n        # ConversationIdFactory can return either a SkillConversationReference (the newer way),\n        # or a ConversationReference (the old way, but still here for compatibility).  If a\n        # ConversationReference is returned, build a new SkillConversationReference to simplify\n        # the remainder of this method.\n        skill_conversation_reference: SkillConversationReference = None\n        if isinstance(conversation_reference_result, SkillConversationReference):\n            skill_conversation_reference = conversation_reference_result\n        else:\n            skill_conversation_reference = SkillConversationReference(\n                conversation_reference=conversation_reference_result,\n                oauth_scope=(\n                    GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\n                    if self._channel_provider and self._channel_provider.is_government()\n                    else AuthenticationConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\n                ),\n            )\n\n        if not skill_conversation_reference:\n            raise KeyError(\"SkillConversationReference not found\")\n\n        if not skill_conversation_reference.conversation_reference:\n            raise KeyError(\"conversationReference not found\")\n\n        # If an activity is sent, return the ResourceResponse\n        resource_response: ResourceResponse = None\n\n        async def callback(context: TurnContext):\n            nonlocal resource_response\n            context.turn_state[\n                SkillHandler.SKILL_CONVERSATION_REFERENCE_KEY\n            ] = skill_conversation_reference\n\n            TurnContext.apply_conversation_reference(\n                activity, skill_conversation_reference.conversation_reference\n            )\n\n            context.activity.id = reply_to_activity_id\n\n            app_id = JwtTokenValidation.get_app_id_from_claims(claims_identity.claims)\n            context.activity.caller_id = (\n                f\"{CallerIdConstants.bot_to_bot_prefix}{app_id}\"\n            )\n\n            if activity.type == ActivityTypes.end_of_conversation:\n                await self._conversation_id_factory.delete_conversation_reference(\n                    conversation_id\n                )\n                self._apply_eoc_to_turn_context_activity(context, activity)\n                await self._bot.on_turn(context)\n            elif activity.type == ActivityTypes.event:\n                self._apply_event_to_turn_context_activity(context, activity)\n                await self._bot.on_turn(context)\n            else:\n                resource_response = await context.send_activity(activity)\n\n        await self._adapter.continue_conversation(\n            skill_conversation_reference.conversation_reference,\n            callback,\n            claims_identity=claims_identity,\n            audience=skill_conversation_reference.oauth_scope,\n        )\n\n        if not resource_response:\n            resource_response = ResourceResponse(id=str(uuid4()))\n\n        return resource_response\n\n    @staticmethod\n    def _apply_eoc_to_turn_context_activity(\n        context: TurnContext, end_of_conversation_activity: Activity\n    ):\n        context.activity.type = end_of_conversation_activity.type\n        context.activity.text = end_of_conversation_activity.text\n        context.activity.code = end_of_conversation_activity.code\n\n        context.activity.reply_to_id = end_of_conversation_activity.reply_to_id\n        context.activity.value = end_of_conversation_activity.value\n        context.activity.entities = end_of_conversation_activity.entities\n        context.activity.locale = end_of_conversation_activity.locale\n        context.activity.local_timestamp = end_of_conversation_activity.local_timestamp\n        context.activity.timestamp = end_of_conversation_activity.timestamp\n        context.activity.channel_data = end_of_conversation_activity.channel_data\n        context.activity.additional_properties = (\n            end_of_conversation_activity.additional_properties\n        )\n\n    @staticmethod\n    def _apply_event_to_turn_context_activity(\n        context: TurnContext, event_activity: Activity\n    ):\n        context.activity.type = event_activity.type\n        context.activity.name = event_activity.name\n        context.activity.value = event_activity.value\n        context.activity.relates_to = event_activity.relates_to\n\n        context.activity.reply_to_id = event_activity.reply_to_id\n        context.activity.value = event_activity.value\n        context.activity.entities = event_activity.entities\n        context.activity.locale = event_activity.locale\n        context.activity.local_timestamp = event_activity.local_timestamp\n        context.activity.timestamp = event_activity.timestamp\n        context.activity.channel_data = event_activity.channel_data\n        context.activity.additional_properties = event_activity.additional_properties\n", "path": "libraries/botbuilder-core/botbuilder/core/skills/skill_handler.py"}]}