Conversation
c03ea73 to
fdbb1bd
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the SDK’s quoted-reply support to use Teams’ modern quotedReply entity + <quoted messageId="..."/> placeholder format, adds APIs for creating/reading quoted replies, and introduces tests + a sample app to exercise the new behavior.
Changes:
- Introduces
QuotedReplyEntity/QuotedReplyDataand registers it in the entity JSON converter. - Adds
GetQuotedMessages()andAddQuotedReply(...)onMessageActivity, and updatesContext.Reply(...)plus newContext.QuoteReply(...)helpers to stamp quoted-reply metadata. - Adds unit tests and a new
Samples.QuotedRepliesproject demonstrating end-to-end usage.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/Microsoft.Teams.Apps.Tests/Microsoft.Teams.Apps.Tests.csproj | Suppresses experimental diagnostic for quoted replies in Apps tests. |
| Tests/Microsoft.Teams.Apps.Tests/Contexts/ContextQuotedReplyTests.cs | Adds context-level tests validating Reply() / QuoteReply() stamping behavior. |
| Tests/Microsoft.Teams.Api.Tests/Microsoft.Teams.Api.Tests.csproj | Suppresses experimental diagnostic for quoted replies in Api tests. |
| Tests/Microsoft.Teams.Api.Tests/Json/Entities/QuotedReplyEntity.json | Adds golden JSON payload for quoted reply entity serialization tests. |
| Tests/Microsoft.Teams.Api.Tests/Entities/QuotedReplyEntityTests.cs | Adds serialization/deserialization and helper API tests for quoted replies. |
| Samples/Samples.QuotedReplies/appsettings.json | Adds sample configuration for the quoted replies demo app. |
| Samples/Samples.QuotedReplies/Samples.QuotedReplies.csproj | Adds new sample project wired to experimental quoted-reply APIs. |
| Samples/Samples.QuotedReplies/README.md | Documents sample commands and quoted-reply usage patterns. |
| Samples/Samples.QuotedReplies/Properties/launchSettings.TEMPLATE.json | Adds launch profile template for the new sample. |
| Samples/Samples.QuotedReplies/Program.cs | Implements demo bot behavior showing read/write quoted replies. |
| Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs | Updates Reply() quoting behavior and adds QuoteReply() context APIs. |
| Libraries/Microsoft.Teams.Api/Entities/QuotedReplyEntity.cs | Adds the new quoted reply entity types. |
| Libraries/Microsoft.Teams.Api/Entities/Entity.cs | Registers quotedReply in entity JSON (de)serialization. |
| Libraries/Microsoft.Teams.Api/Activities/Message/MessageActivity.cs | Adds GetQuotedMessages() and AddQuotedReply(...) builder. |
| Libraries/Microsoft.Teams.Api/Activities/Activity.cs | Removes WithReplyToId(), updates ToQuoteReply() and marks it obsolete. |
Comments suppressed due to low confidence (1)
Libraries/Microsoft.Teams.Api/Activities/Activity.cs:201
WithReplyToId(string)was removed fromActivity. If this library has external consumers, removing a public fluent setter is a breaking change; it may be safer to keep the method and mark it[Obsolete](or provide a compatible alternative) to avoid forcing downstream recompiles/changes.
public virtual Activity WithId(string value)
{
Id = value;
return this;
}
public virtual Activity WithChannelId(ChannelId value)
{
ChannelId = value;
return this;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
Libraries/Microsoft.Teams.Api/Activities/Activity.cs:203
WithReplyToId(string)was removed from the fluentActivityAPI. Since the rest ofWithXyz(...)methods remain, removing this public method is a source/binary breaking change for consumers that used it to setReplyToId. Consider keeping it (at least temporarily) as an[Obsolete]shim that assignsReplyToIdand returnsthis, or ensure the breaking change is intentional and called out in release notes/versioning.
public virtual Activity WithId(string value)
{
Id = value;
return this;
}
public virtual Activity WithChannelId(ChannelId value)
{
ChannelId = value;
return this;
}
public virtual Activity WithFrom(Account value)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
67ba64a to
52c5002
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Libraries/Microsoft.Teams.Api/Activities/Message/MessageActivity.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Reply<T>() now delegates to QuoteReply<T>() when Activity.Id is set - QuoteReply<T>() only stamps entity + placeholder for MessageActivity - Remove redundant conversation copy (AspNetCorePlugin.Send overwrites it) - Update test fixture time values to IC3 epoch format Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
Libraries/Microsoft.Teams.Api/Activities/Activity.cs:201
WithReplyToId(string value)was removed fromActivity, which is a breaking change for consumers relying on the fluent builder API. If the goal is to deprecate this surface, consider keeping the method and marking it[Obsolete](or providing an alternative builder) rather than removing it outright, and ensure the change is reflected in the public API/semver strategy.
public virtual Activity WithId(string value)
{
Id = value;
return this;
}
public virtual Activity WithChannelId(ChannelId value)
{
ChannelId = value;
return this;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// <summary> | ||
| /// send an activity to the conversation as a reply | ||
| /// send an activity to the conversation as a reply, automatically quoting the inbound message | ||
| /// </summary> | ||
| /// <param name="activity">activity activity to send</param> | ||
| /// <param name="activity">activity to send</param> | ||
| /// <param name="cancellationToken">optional cancellation token</param> | ||
| public Task<T> Reply<T>(T activity, CancellationToken cancellationToken = default) where T : IActivity; | ||
|
|
||
| /// <summary> | ||
| /// send a message activity to the conversation as a reply | ||
| /// send a message activity to the conversation as a reply, automatically quoting the inbound message | ||
| /// </summary> |
There was a problem hiding this comment.
The XML docs for Reply(...) say it “automatically quotes the inbound message”, but the implementation only prepends a quote for MessageActivity (non-message activities pass through unchanged). Please clarify the docs (e.g., “for message activities”) to match the actual behavior and avoid misleading consumers.
| /// <summary> | ||
| /// Send a message to the conversation with a quoted message reference prepended to the text. | ||
| /// Teams renders the quoted message as a preview bubble above the response text. | ||
| /// </summary> | ||
| /// <param name="messageId">the ID of the message to quote</param> | ||
| /// <param name="activity">the activity to send — a quote placeholder for messageId will be prepended to its text</param> | ||
| /// <param name="cancellationToken">optional cancellation token</param> | ||
| [Experimental("ExperimentalTeamsQuotedReplies")] | ||
| public Task<T> Quote<T>(string messageId, T activity, CancellationToken cancellationToken = default) where T : IActivity; | ||
|
|
There was a problem hiding this comment.
Quote<T>(string messageId, T activity, ...) is documented as “Send a message … with a quoted message reference prepended”, but the method accepts any IActivity and only mutates MessageActivity. Consider constraining this overload to MessageActivity (and/or adding a MessageActivity-specific overload) or updating the docs to state that quoting is applied only when activity is a MessageActivity.
| <Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net10.0</TargetFramework> | ||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <NoWarn>$(NoWarn);ExperimentalTeamsQuotedReplies</NoWarn> | ||
| </PropertyGroup> |
There was a problem hiding this comment.
PR description mentions adding a Samples.QuotedReplies sample, but the added sample project is Samples.Quoting. Please align the PR description (and any external docs) with the actual sample name/path to avoid confusion for readers.
ed385fb to
90cbb31
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
Libraries/Microsoft.Teams.Api/Activities/Activity.cs:201
- Removing the public fluent helper
WithReplyToId(...)is a breaking change for consumers (especially those using the builder-style API), even ifReplyToIdremains. Consider keeping the method as[Obsolete](forwarding toReplyToId) for at least one release, or ensure this ships with an appropriate major version bump/release note.
public virtual Activity WithId(string value)
{
Id = value;
return this;
}
public virtual Activity WithChannelId(ChannelId value)
{
ChannelId = value;
return this;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Example: Quoting | ||
|
|
||
| A bot that demonstrates various ways to quote previous messages in Microsoft Teams. |
There was a problem hiding this comment.
PR description mentions adding a Samples.QuotedReplies sample, but this PR adds Samples/Samples.Quoting. Either update the PR description to match the actual sample name/path or rename the sample folder/project to avoid confusion for readers.
|
Re: Copilot review comments
|
WithReplyToId(), updateToQuoteReply()and mark it[Obsolete]QuotedReplyEntitywith nestedQuotedReplyData(MessageIdrequired,SenderId/SenderName/Preview/Time/IsReplyDeleted/ValidatedMessageReferenceoptional); register in Entity JSON converterGetQuotedMessages()onMessageActivityto read inbound quoted reply entitiesAddQuote(messageId, text?)builder onMessageActivity(appends quote placeholder + optional text)PrependQuote(messageId)onMessageActivity(prepends quote placeholder before existing text, used internally byReply()/Quote())Reply()to delegate toQuote()whenActivity.Idis set; remove conversation copy (redundant —AspNetCorePlugin.Send()handles it) and;messageid=stripping (redundant — APX normalizes server-side)Quote()on context — sends a message with a quoted message reference prepended to the text. Entity + placeholder only stamped forMessageActivity.[Experimental("ExperimentalTeamsQuotedReplies")]Reply()andQuote()