Skip to content

Update quoted replies & new quotes features#389

Merged
corinagum merged 15 commits into
mainfrom
cg/quoted-replies
May 7, 2026
Merged

Update quoted replies & new quotes features#389
corinagum merged 15 commits into
mainfrom
cg/quoted-replies

Conversation

@corinagum

@corinagum corinagum commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator
image
  • Remove WithReplyToId(), update ToQuoteReply() and mark it [Obsolete]
  • Add QuotedReplyEntity with QuotedReplyData (MessageId required, SenderId/SenderName/Preview/Time/IsReplyDeleted/ValidatedMessageReference optional); register in Entity JSON converter
  • Add GetQuotedMessages() on MessageActivity to read inbound quoted reply entities
  • Add AddQuote(messageId, text?) builder on MessageActivity (appends quote placeholder + optional text)
  • Add PrependQuote(messageId) on MessageActivity (prepends quote placeholder before existing text, used internally by Reply()/Quote())
  • Update Reply() to delegate to Quote() when Activity.Id is set; remove conversation copy (redundant — AspNetCorePlugin.Send() handles it) and ;messageid= stripping (redundant — APX normalizes server-side)
  • Add Quote() on context — sends a message with a quoted message reference prepended to the text. Entity + placeholder only stamped for MessageActivity.
  • Mark all quoted reply types and methods as [Experimental("ExperimentalTeamsQuotedReplies")]
  • Add context-level unit tests for Reply() and Quote()
  • Add Samples.Quoting sample exercising all APIs

@corinagum
corinagum marked this pull request as ready for review March 24, 2026 18:19
Copilot AI review requested due to automatic review settings March 24, 2026 18:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 / QuotedReplyData and registers it in the entity JSON converter.
  • Adds GetQuotedMessages() and AddQuotedReply(...) on MessageActivity, and updates Context.Reply(...) plus new Context.QuoteReply(...) helpers to stamp quoted-reply metadata.
  • Adds unit tests and a new Samples.QuotedReplies project 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 from Activity. 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.

Comment thread Libraries/Microsoft.Teams.Api/Entities/QuotedReplyEntity.cs
Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs Outdated
@corinagum corinagum changed the title Update quoted replies Update quoted replies & new quotes features Mar 25, 2026
Copilot AI review requested due to automatic review settings March 25, 2026 21:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 fluent Activity API. Since the rest of WithXyz(...) methods remain, removing this public method is a source/binary breaking change for consumers that used it to set ReplyToId. Consider keeping it (at least temporarily) as an [Obsolete] shim that assigns ReplyToId and returns this, 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.

Comment thread Libraries/Microsoft.Teams.Api/Entities/QuotedReplyEntity.cs
Comment thread Samples/Samples.Quoting/README.md
Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs Outdated
Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs Outdated
Copilot AI review requested due to automatic review settings March 26, 2026 00:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs
Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs
Comment thread Libraries/Microsoft.Teams.Api/Activities/Message/MessageActivity.cs Outdated
Comment thread Libraries/Microsoft.Teams.Api/Activities/Activity.cs
Comment thread Libraries/Microsoft.Teams.Api/Activities/Message/MessageActivity.cs
Copilot AI review requested due to automatic review settings March 26, 2026 23:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs
Comment thread Samples/Samples.QuotedReplies/Program.cs Outdated
Comment thread Samples/Samples.QuotedReplies/README.md Outdated
Comment thread Libraries/Microsoft.Teams.Api/Activities/Message/MessageActivity.cs
Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs
Copilot AI review requested due to automatic review settings April 2, 2026 01:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 from Activity, 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.

Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs
Comment thread Libraries/Microsoft.Teams.Apps/Contexts/Context.Send.cs
Comment thread Samples/Samples.Quoting/Samples.Quoting.csproj
@corinagum
corinagum force-pushed the cg/quoted-replies branch from ed385fb to 90cbb31 Compare April 2, 2026 01:39
Copilot AI review requested due to automatic review settings April 2, 2026 01:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 if ReplyToId remains. Consider keeping the method as [Obsolete] (forwarding to ReplyToId) 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.

Comment thread Samples/Samples.Quoting/README.md
@corinagum
corinagum force-pushed the cg/quoted-replies branch 2 times, most recently from 334edf4 to 9243e81 Compare April 7, 2026 19:16
Copilot AI review requested due to automatic review settings April 22, 2026 21:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:202

  • Removing the public WithReplyToId(string) fluent builder is a source/binary breaking change for consumers, especially since the ReplyToId property still exists on the model. If this removal is intentional, consider leaving an [Obsolete] forwarding method for at least one release (or documenting the migration path) to reduce upgrade friction.
    public virtual string GetPath() => string.Join(".", ["Activity", Type.ToPrettyString()]);

    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.

Comment thread Libraries/Microsoft.Teams.Api/Entities/QuotedReplyEntity.cs
@corinagum
corinagum force-pushed the cg/quoted-replies branch from b8a221b to a7a23dd Compare May 6, 2026 23:51
Corina Gum and others added 15 commits May 7, 2026 13:24
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
- 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) <[email protected]>
Copilot AI review requested due to automatic review settings May 7, 2026 20:24
@corinagum
corinagum force-pushed the cg/quoted-replies branch from a7a23dd to b8cafea Compare May 7, 2026 20:24
@corinagum
corinagum merged commit 6e7e857 into main May 7, 2026
10 checks passed
@corinagum
corinagum deleted the cg/quoted-replies branch May 7, 2026 20:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

@@ -192,12 +194,6 @@ public virtual Activity WithId(string value)
return this;
}

Comment on lines 108 to +112
public Task<T> Reply<T>(T activity, CancellationToken cancellationToken = default) where T : IActivity
{
activity.Conversation = Ref.Conversation.Copy();
activity.Conversation.Id = Ref.Conversation.ThreadId;

if (activity is MessageActivity message)
if (Activity.Id != null)
{
message.Text = string.Join("\n", [
Activity.ToQuoteReply(),
message.Text != string.Empty ? $"<p>{message.Text}</p>" : string.Empty
]);
return Quote(Activity.Id, activity, cancellationToken);
Comment on lines +1 to +8
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>$(NoWarn);ExperimentalTeamsQuotedReplies</NoWarn>
</PropertyGroup>
corinagum added a commit that referenced this pull request May 15, 2026
## Summary

Brings `main` into `releases/v2` for the 2.0.7 Libraries release, with
quoted-replies (PR #389) excluded. Scope is **Legacy / Libraries only**
— `core/` is not in scope for this release.

Single squashed commit.

## What's in this release

- All commits merged to main since 2.0.6 (the previous Libraries
release), notably:
- **Reactions GA** (PR #509) —
`[Experimental("ExperimentalTeamsReactions")]` removed across Libraries
  - Prompt Preview Support (PR #433)
  - MCP server auth security hardening (PR #448)
  - Various dependency bumps and bug fixes

## What's NOT in this release

**Quoted-replies feature (PR #389) is excluded:**
- `MessageActivity.AddQuote()`, `PrependQuote()` builder methods —
absent
- `Context.Reply()` quote-aware behavior — reverted to legacy
`replyToId` + blockquote
- `Samples/Samples.Quoting` — removed
- QR-related tests — removed

**Kept intentionally:**
- `QuotedReplyEntity` and `QuotedReplyData` types stay in
`Microsoft.Teams.Api.Entities` (still annotated
`[Experimental("ExperimentalTeamsQuotedReplies")]`) so inbound
activities carrying `quotedReply` entities still parse
- `MessageActivity.AddTargetedMessageInfo` runtime strip-QR logic —
preserves prompt-preview cleanup
- Entity.cs serializer cases for `quotedReply` (with existing `#pragma
warning disable ExperimentalTeamsQuotedReplies`)

## Version

`version.json`: `2.0.6` → `2.0.7`

## Scope

**Libraries only.** `core/` (the `releases/core` track) is not affected
by this PR — when this prep merges to `releases/v2`, the `core/` tree
may appear in the branch as part of the merge, but the Legacy publish
pipeline only builds and ships from `Libraries/`, `Samples/`, and
`Tests/`.

## Test plan

- [x] `dotnet build Microsoft.Teams.sln --configuration Release` — 0
errors, 5 pre-existing warnings
- [x] `dotnet test Microsoft.Teams.sln --configuration Release` — all
suites pass across net8.0 and net10.0 (Api 407+407, Apps 136+136, Common
63+63, AI 17+17, McpClient 9+9, Graph 3+3, AspNetCore 25+25 with 1
pre-existing skip)
- [x] `dotnet pack` — nupkgs produced; consumer install verified (fresh
console project, `dotnet add package Microsoft.Teams.Apps --prerelease`,
`dotnet run` confirms `QuotedReplyEntity` ships,
`AddQuote`/`PrependQuote` absent, `AddTargetedMessageInfo` present,
`ReactionClient.AddAsync`/`DeleteAsync` present)
- [ ] Teams.NET-ESRP pipeline with `packageSet=Legacy`,
`publishType=Public` (post-merge)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants