Skip to content
This repository was archived by the owner on Jan 5, 2026. It is now read-only.

Commit 30bce78

Browse files
authored
Merge pull request #1415 from microsoft/axsuarez/TranscriptLoggerShouldNotLogContinueConversation
TranscriptLogger should not log continue conversation
2 parents d8e338e + 4897c72 commit 30bce78

File tree

9 files changed

+89
-8
lines changed

9 files changed

+89
-8
lines changed

libraries/botbuilder-core/botbuilder/core/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from .telemetry_logger_constants import TelemetryLoggerConstants
4040
from .telemetry_logger_middleware import TelemetryLoggerMiddleware
4141
from .turn_context import TurnContext
42+
from .transcript_logger import TranscriptLogger, TranscriptLoggerMiddleware
4243
from .user_state import UserState
4344
from .register_class_middleware import RegisterClassMiddleware
4445
from .adapter_extensions import AdapterExtensions
@@ -87,6 +88,8 @@
8788
"TelemetryLoggerConstants",
8889
"TelemetryLoggerMiddleware",
8990
"TopIntent",
91+
"TranscriptLogger",
92+
"TranscriptLoggerMiddleware",
9093
"TurnContext",
9194
"UserState",
9295
"UserTokenProvider",

libraries/botbuilder-core/botbuilder/core/adapters/test_adapter.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ async def create_conversation(
225225
type=ActivityTypes.conversation_update,
226226
members_added=[],
227227
members_removed=[],
228+
channel_id=channel_id,
228229
conversation=ConversationAccount(id=str(uuid.uuid4())),
229230
)
230231
context = self.create_turn_context(update)

libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
)
4040
from botbuilder.schema import (
4141
Activity,
42+
ActivityEventNames,
4243
ActivityTypes,
4344
ChannelAccount,
4445
ConversationAccount,
@@ -390,7 +391,7 @@ async def create_conversation(
390391

391392
event_activity = Activity(
392393
type=ActivityTypes.event,
393-
name="CreateConversation",
394+
name=ActivityEventNames.create_conversation,
394395
channel_id=channel_id,
395396
service_url=service_url,
396397
id=resource_response.activity_id

libraries/botbuilder-core/botbuilder/core/conversation_reference_extension.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33
import uuid
4-
from botbuilder.schema import Activity, ActivityTypes, ConversationReference
4+
from botbuilder.schema import (
5+
Activity,
6+
ActivityEventNames,
7+
ActivityTypes,
8+
ConversationReference,
9+
)
510

611

712
def get_continuation_activity(reference: ConversationReference) -> Activity:
813
return Activity(
914
type=ActivityTypes.event,
10-
name="ContinueConversation",
15+
name=ActivityEventNames.continue_conversation,
1116
id=str(uuid.uuid1()),
1217
channel_id=reference.channel_id,
1318
service_url=reference.service_url,

libraries/botbuilder-core/botbuilder/core/memory_transcript_store.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from botbuilder.schema import Activity
77
from .transcript_logger import PagedResult, TranscriptInfo, TranscriptStore
88

9+
910
# pylint: disable=line-too-long
1011
class MemoryTranscriptStore(TranscriptStore):
1112
"""This provider is most useful for simulating production storage when running locally against the
@@ -59,7 +60,9 @@ async def get_transcript_activities(
5960
[
6061
x
6162
for x in sorted(
62-
transcript, key=lambda x: x.timestamp, reverse=False
63+
transcript,
64+
key=lambda x: x.timestamp or str(datetime.datetime.min),
65+
reverse=False,
6366
)
6467
if x.timestamp >= start_date
6568
]
@@ -72,9 +75,11 @@ async def get_transcript_activities(
7275
paged_result.items = [
7376
x
7477
for x in sorted(
75-
transcript, key=lambda x: x.timestamp, reverse=False
78+
transcript,
79+
key=lambda x: x.timestamp or datetime.datetime.min,
80+
reverse=False,
7681
)
77-
if x.timestamp >= start_date
82+
if (x.timestamp or datetime.datetime.min) >= start_date
7883
][:20]
7984
if paged_result.items.count == 20:
8085
paged_result.continuation_token = paged_result.items[-1].id

libraries/botbuilder-core/botbuilder/core/transcript_logger.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
from queue import Queue
1010
from abc import ABC, abstractmethod
1111
from typing import Awaitable, Callable, List
12-
from botbuilder.schema import Activity, ActivityTypes, ConversationReference
12+
from botbuilder.schema import (
13+
Activity,
14+
ActivityEventNames,
15+
ActivityTypes,
16+
ChannelAccount,
17+
ConversationReference,
18+
)
1319
from .middleware_set import Middleware
1420
from .turn_context import TurnContext
1521

@@ -46,9 +52,17 @@ async def on_turn(
4652
activity = context.activity
4753
# Log incoming activity at beginning of turn
4854
if activity:
55+
if not activity.from_property:
56+
activity.from_property = ChannelAccount()
4957
if not activity.from_property.role:
5058
activity.from_property.role = "user"
51-
await self.log_activity(transcript, copy.copy(activity))
59+
60+
# We should not log ContinueConversation events used by skills to initialize the middleware.
61+
if not (
62+
context.activity.type == ActivityTypes.event
63+
and context.activity.name == ActivityEventNames.continue_conversation
64+
):
65+
await self.log_activity(transcript, copy.copy(activity))
5266

5367
# hook up onSend pipeline
5468
# pylint: disable=unused-argument
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
import aiounittest
5+
6+
from botbuilder.core import (
7+
MemoryTranscriptStore,
8+
TranscriptLoggerMiddleware,
9+
TurnContext,
10+
)
11+
from botbuilder.core.adapters import TestAdapter, TestFlow
12+
from botbuilder.schema import Activity, ActivityEventNames, ActivityTypes
13+
14+
15+
class TestTranscriptLoggerMiddleware(aiounittest.AsyncTestCase):
16+
async def test_should_not_log_continue_conversation(self):
17+
transcript_store = MemoryTranscriptStore()
18+
conversation_id = ""
19+
sut = TranscriptLoggerMiddleware(transcript_store)
20+
21+
async def aux_logic(context: TurnContext):
22+
nonlocal conversation_id
23+
conversation_id = context.activity.conversation.id
24+
25+
adapter = TestAdapter(aux_logic)
26+
adapter.use(sut)
27+
28+
continue_conversation_activity = Activity(
29+
type=ActivityTypes.event, name=ActivityEventNames.continue_conversation
30+
)
31+
32+
test_flow = TestFlow(None, adapter)
33+
step1 = await test_flow.send("foo")
34+
step2 = await step1.send("bar")
35+
await step2.send(continue_conversation_activity)
36+
37+
paged_result = await transcript_store.get_transcript_activities(
38+
"test", conversation_id
39+
)
40+
self.assertEqual(
41+
len(paged_result.items),
42+
2,
43+
"only the two message activities should be logged",
44+
)

libraries/botbuilder-schema/botbuilder/schema/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Licensed under the MIT License.
33

44
from ._models_py3 import Activity
5+
from ._models_py3 import ActivityEventNames
56
from ._models_py3 import AnimationCard
67
from ._models_py3 import Attachment
78
from ._models_py3 import AttachmentData
@@ -74,6 +75,7 @@
7475

7576
__all__ = [
7677
"Activity",
78+
"ActivityEventNames",
7779
"AnimationCard",
7880
"Attachment",
7981
"AttachmentData",

libraries/botbuilder-schema/botbuilder/schema/_models_py3.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@
33

44
from botbuilder.schema._connector_client_enums import ActivityTypes
55
from datetime import datetime
6+
from enum import Enum
67
from msrest.serialization import Model
78
from msrest.exceptions import HttpOperationError
89

910

11+
class ActivityEventNames(str, Enum):
12+
continue_conversation = "ContinueConversation"
13+
create_conversation = "CreateConversation"
14+
15+
1016
class ConversationReference(Model):
1117
"""An object relating to a particular point in a conversation.
1218

0 commit comments

Comments
 (0)