Skip to content

fix(apps): source informative textFormat from the update + add textFormat to update() - #784

Merged
Kavin (singhk97) merged 10 commits into
mainfrom
copilot/stream-update-textformat
Sep 1, 2026
Merged

fix(apps): source informative textFormat from the update + add textFormat to update()#784
Kavin (singhk97) merged 10 commits into
mainfrom
copilot/stream-update-textformat

Conversation

@singhk97

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #762. Two fixes for textFormat on streamed informative updates:

  1. Source informative textFormat from the update itself. In HttpStream.flush(), informative typing chunks previously took their format from this.finalActivity?.textFormat. But finalActivity is only set once a message is drained from the queue — which happens after informative updates are collected — so an informative update's own textFormat was ignored. It now reads informativeUpdate.textFormat directly. The streamed-text chunk keeps its correct last-emitted-message-wins behavior.

  2. update() can now carry a textFormat. IStreamer.update(text) / HttpStream.update(text) gain an optional, nullable textFormat:

    update(text: string, textFormat?: TextFormat | null): void;

    undefined/null → Teams default (markdown); an explicit value (e.g. extendedmarkdown) → that format. Previously the only way to format an informative update was to hand-build a { type: 'typing', ..., textFormat } object and call emit().

Sample

examples/stream demonstrates the new update() overload and cleans up the extended-markdown scenario's deltas to match the existing sample style while showcasing checkboxes and strikethrough.

Tests

Added to http-stream.spec.ts:

  • informative update carries its own textFormat, independent of finalActivity (red/green — fails against the old finalActivity-sourced logic)
  • update(text, 'extendedmarkdown') sends an informative chunk with that format
  • update(text) and update(text, null) omit textFormat

All apps tests pass (648/648), build + eslint clean.

Cross-language

Counterpart PRs (not yet merged) will fold in the equivalent changes:

GitHub Copilot and others added 6 commits August 25, 2026 21:11
…ities

HttpStream rebuilds outbound wire activities (TypingActivityInput chunks and
the final MessageActivityInput) from scratch each flush/close cycle. It
already carries forward attachments, entities, suggested actions, and
channelData from the last emitted message ("last message wins"), but did not
carry forward textFormat, so `stream.emit({ type: "message", text,
textFormat: "extendedmarkdown" })` was silently dropped from every
intermediate typing chunk and the final message. The timeout/plain-final
fallback (sendFinal) had the same gap.

- Model textFormat on ITypingActivity/TypingActivityInput (previously only
  modeled on message activities), with a withTextFormat() builder method,
  mirroring MessageActivityInput.
- HttpStream now reads the last emitted message's textFormat off
  this.finalActivity (the existing last-message-wins state) and applies it to
  every cumulative typing chunk, informative typing updates, the normal final
  message, and the timed-out plain-final fallback.
- Add unit tests covering textFormat propagation across intermediate chunks,
  the final message, and the timeout fallback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mple

Adds an 'extended-markdown' trigger that streams a release-status update where each delta sets textFormat: 'extendedmarkdown', so task lists and strikethrough render while streaming. Also trims verbose textFormat comments per review feedback.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
…Format to update()

Informative streaming updates now read textFormat from the update itself instead of the not-yet-set finalActivity, and IStreamer.update()/HttpStream.update() accept an optional nullable textFormat forwarded onto the informative typing activity.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
# Conflicts:
#	examples/stream/src/index.ts
#	packages/apps/src/http/http-stream.spec.ts
#	packages/apps/src/http/http-stream.ts
…am sample style

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
… normalization)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
Copilot AI lite review requested due to automatic review settings August 31, 2026 19:27
Comment thread packages/apps/src/types/streamer.ts

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 fixes how textFormat is handled for streamed informative typing updates in HttpStream, and extends the streaming API so update() can explicitly control formatting without requiring callers to hand-build a typing activity.

Changes:

  • Fix HttpStream.flush() to source informative update textFormat from the informative update itself (instead of finalActivity).
  • Extend IStreamer.update() / HttpStream.update() to accept an optional, nullable textFormat.
  • Add unit tests covering informative textFormat behavior and the new update() overload; update the streaming example to use the overload.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
packages/apps/src/types/streamer.ts Extends the IStreamer.update() signature and documents textFormat semantics.
packages/apps/src/http/http-stream.ts Implements update(text, textFormat?) and fixes informative update textFormat sourcing in flush().
packages/apps/src/http/http-stream.spec.ts Adds tests for informative textFormat and the new update() overload behavior.
examples/stream/src/index.ts Updates the extended-markdown sample to use the new update() overload and refreshes sample deltas.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/apps/src/http/http-stream.ts
…escribing

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
…OWN_MESSAGES

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0073e3f0-b7b4-464a-9bdf-30f97d8081ec
Kavin (singhk97) added a commit to microsoft/teams.py that referenced this pull request Aug 31, 2026
…format to update()

Port of microsoft/teams.ts#784 (follow-up to #762).

- HttpStream._flush() no longer overwrites an informative update's own
  text_format with the last emitted message's format; informative chunks
  now keep the value set on the update itself.
- StreamerProtocol.update / HttpStream.update gain an optional text_format
  arg so informative updates can carry a format without hand-building a
  typing activity.
- examples/stream: refresh the extended-markdown scenario and use the new
  update(text, 'markdown') overload.
- Tests for informative-update format independence and the update() overload.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Kavin (singhk97) added a commit to microsoft/teams.py that referenced this pull request Sep 1, 2026
…vities (#581)

## Summary

Ports
[microsoft/teams.ts#762](microsoft/teams.ts#762)
and its follow-up [#784](microsoft/teams.ts#784)
to the Python SDK.

On every `flush()`, `HttpStream` rebuilds the outbound typing chunk and
forwards the last emitted message's attachments, entities, suggested
actions, and channel data ("last message wins" via
`self._final_activity`) — but not `text_format`. So
`stream.emit(MessageActivityInput(text=...).with_text_format("extendedmarkdown"))`
was dropped from every intermediate chunk, and streamed Extended
Markdown (task lists, strikethrough) rendered as plain markdown until
the message closed.

The final message and timeout fallback (`_send_final`) already preserved
`text_format`, since they reuse the real `_final_activity` object rather
than rebuilding a copy (unlike TS). Only the streamed chunks needed
fixing.

## Changes

- Add `text_format` + a `with_text_format()` builder to `_TypingBase`
(shared by `TypingActivity` / `TypingActivityInput`), mirroring
`MessageActivityInput`.
- `HttpStream._flush()` applies the last emitted message's `text_format`
to the combined streamed-text chunk (last-message-wins).
- **Informative updates keep their own `text_format`.** `_flush()`
previously overwrote each informative update's format with
`_final_activity.text_format`; it now leaves the update's own value
intact (`_final_activity` isn't even set when informative updates are
sent).
- **`update()` gains an optional `text_format`.**
`StreamerProtocol.update` / `HttpStream.update` now accept
`text_format`; `None` → Teams default (`markdown`), an explicit value →
that format. Previously the only way to format an informative update was
to hand-build a typing activity and `emit()` it.
- `examples/stream`: refresh the `extended-markdown` scenario and demo
the new `update(text, "markdown")` overload.
- Unit tests for `text_format` on typing activities, its propagation
across streamed chunks / final message / timeout fallback,
informative-update format independence (red/green against the old
overwrite), and the `update()` overload.

## Testing

- `ruff format --check`, `ruff check`, `pyright`, `pytest packages`
(1107 passed) — all pass.
- Verified live in Teams: streaming a message with
`text_format="extendedmarkdown"` renders task lists and strikethrough on
each intermediate chunk.

_Created from a [Microsoft Teams
conversation](https://teams.microsoft.com/l/message/19%3AeXvmZeTKJ1Myy2_qfz4vp4-YjeIqCMJ4xF6poI2GxtU1%40thread.tacv2/1787691375435?tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47&groupId=1314f851-c930-4caa-b3e0-dbe9b8fe2737&parentMessageId=1787691375435)._

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Kavin Singh <kavinsingh@microsoft.com>
Co-authored-by: Kavin <115390646+singhk97@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@singhk97
Kavin (singhk97) added this pull request to the merge queue Sep 1, 2026
Merged via the queue into main with commit 81812fb Sep 1, 2026
9 checks passed
@singhk97
Kavin (singhk97) deleted the copilot/stream-update-textformat branch September 1, 2026 20:14
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