Telegram: attribute forwarded messages #25

Closed
opened 2026-07-05 07:49:03 +08:00 by weiwen · 1 comment
Owner

What to build

Let evie recognize forwarded Telegram messages and mark them as such, so pi knows the content originated elsewhere. Today a forward is treated as an ordinary message with no signal that it was forwarded.

When a message has forward metadata (forward_origin), evie prepends a compact attribution line and passes the content verbatim:

  • [Forwarded from <origin>, <date>] when the origin is available (user, hidden user, chat, or channel — whatever MessageOrigin exposes).
  • Degrade to a bare [Forwarded] when the origin is hidden/unavailable.
  • No injected instruction, no caption requirement — pi decides what to do with a forward (mechanism in evie, policy in the system prompt).

The attribution is orthogonal to content type: it composes with the existing text and photo handlers, and with the document (#24) and location (#23) branches when those are present — a forwarded document gets both the prefix and the document handling, a forwarded pin gets the prefix and the location marker. This slice carries the small restructure that computes the forward prefix once and prepends it to whichever content branch runs.

Acceptance criteria

  • Forwarding a text message prepends [Forwarded from <origin>, <date>] before the content and produces a normal streamed reply
  • When the origin is hidden/unavailable, a bare [Forwarded] marker is used
  • The prefix composes with the photo branch (forwarded photo gets prefix + image handling); it also composes with the document and location branches if those are already merged
  • No caption is required and no fixed instruction is injected — content passes verbatim after the prefix
  • Non-forwarded messages are unaffected
  • Unit test(s) cover the prefix construction for the available-origin and hidden-origin cases and its composition with at least one content branch

Blocked by

None - can start immediately (composes cleanest atop #24 if that merges first, but is not gated on it)

## What to build Let evie recognize forwarded Telegram messages and mark them as such, so pi knows the content originated elsewhere. Today a forward is treated as an ordinary message with no signal that it was forwarded. When a message has forward metadata (`forward_origin`), evie prepends a compact attribution line and passes the content verbatim: - `[Forwarded from <origin>, <date>]` when the origin is available (user, hidden user, chat, or channel — whatever `MessageOrigin` exposes). - Degrade to a bare `[Forwarded]` when the origin is hidden/unavailable. - No injected instruction, no caption requirement — pi decides what to do with a forward (mechanism in evie, policy in the system prompt). The attribution is orthogonal to content type: it composes with the existing text and photo handlers, and with the document (#24) and location (#23) branches when those are present — a forwarded document gets both the prefix and the document handling, a forwarded pin gets the prefix and the location marker. This slice carries the small restructure that computes the forward prefix once and prepends it to whichever content branch runs. ## Acceptance criteria - [ ] Forwarding a text message prepends `[Forwarded from <origin>, <date>]` before the content and produces a normal streamed reply - [ ] When the origin is hidden/unavailable, a bare `[Forwarded]` marker is used - [ ] The prefix composes with the photo branch (forwarded photo gets prefix + image handling); it also composes with the document and location branches if those are already merged - [ ] No caption is required and no fixed instruction is injected — content passes verbatim after the prefix - [ ] Non-forwarded messages are unaffected - [ ] Unit test(s) cover the prefix construction for the available-origin and hidden-origin cases and its composition with at least one content branch ## Blocked by None - can start immediately (composes cleanest atop #24 if that merges first, but is not gated on it)
Author
Owner

Implemented in branch sandcastle/issue-25 (commit 87513d3).

What was done:

  • Added format_forward_prefix(origin: &MessageOrigin) -> String — maps all four MessageOrigin variants (User, HiddenUser, Chat, Channel) to [Forwarded from <name>, YYYY-MM-DD]; falls back to [Forwarded] when no name is available.
  • Added apply_forward_prefix(extraction, prefix) -> Extraction — pure helper that prepends the prefix to Extraction::Content.text, leaving FileTooLarge and Unhandled untouched.
  • Refactored extract_message_content into raw extraction + apply-prefix, so text, photo, and document branches all get attribution automatically.
  • 5 new unit tests covering: User prefix, HiddenUser prefix, prefix composition with content, None-prefix no-op, and Unhandled pass-through.

No Rust toolchain in sandbox — CI will validate compilation and tests.

Implemented in branch `sandcastle/issue-25` (commit 87513d3). What was done: - Added `format_forward_prefix(origin: &MessageOrigin) -> String` — maps all four `MessageOrigin` variants (User, HiddenUser, Chat, Channel) to `[Forwarded from <name>, YYYY-MM-DD]`; falls back to `[Forwarded]` when no name is available. - Added `apply_forward_prefix(extraction, prefix) -> Extraction` — pure helper that prepends the prefix to `Extraction::Content.text`, leaving `FileTooLarge` and `Unhandled` untouched. - Refactored `extract_message_content` into raw extraction + apply-prefix, so text, photo, and document branches all get attribution automatically. - 5 new unit tests covering: User prefix, HiddenUser prefix, prefix composition with content, None-prefix no-op, and Unhandled pass-through. No Rust toolchain in sandbox — CI will validate compilation and tests.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
weiwen/evie#25
No description provided.