Typed Snapshot: move Telegram preview styling out of the pi transport #32

Closed
opened 2026-07-05 13:10:36 +08:00 by weiwen · 1 comment
Owner

What to build

The pi module — the streaming transport shared by both interfaces — forwards live snapshots as plain strings and bakes in Telegram-specific presentation: a 💭 emoji prefix and a ~3800-char tail-trim derived from Telegram's 4096 message cap. Only the Telegram interface consumes snapshots (the HTTP interface discards them). Forward a typed snapshot from pi and move the presentation into the Telegram interface, so the shared transport stops carrying one interface's display constants.

Justified by locality (not variance — there is only one snapshot consumer today).

Decision from grilling:

// in the pi module (producer owns the wire type)
enum Snapshot { Text(String), Thinking(String) }   // derive PartialEq; dedup stays in pi
  • The streaming channel becomes UnboundedSender<Snapshot> end-to-end (through the session manager and both callers). HTTP passes a detached channel and ignores it.
  • pi emits Text when the assistant message carries text, else Thinking with the raw thinking text — no emoji, no trim.
  • The 💭 prefix and the tail-trim (preview() + the char-limit constant) move into the Telegram interface, which renders Text as-is and Thinking via preview().

Acceptance criteria

  • Snapshot { Text, Thinking } defined in the pi module; snapshot channel retyped end-to-end.
  • pi no longer contains the 💭 prefix or any Telegram-derived char cap; dedup of consecutive identical snapshots stays in pi.
  • The Telegram interface owns the thinking preview (emoji + tail bound); streamed text and the thinking→text flip behave exactly as before.
  • HTTP path still returns the authoritative final answer, unaffected.
  • pi stream-parsing tests updated for the typed snapshots; just check green.

Blocked by

None - can start immediately.

## What to build The pi module — the streaming transport shared by both interfaces — forwards live snapshots as plain strings and bakes in Telegram-specific presentation: a `💭` emoji prefix and a ~3800-char tail-trim derived from Telegram's 4096 message cap. Only the Telegram interface consumes snapshots (the HTTP interface discards them). Forward a **typed** snapshot from pi and move the presentation into the Telegram interface, so the shared transport stops carrying one interface's display constants. Justified by locality (not variance — there is only one snapshot consumer today). Decision from grilling: ```rust // in the pi module (producer owns the wire type) enum Snapshot { Text(String), Thinking(String) } // derive PartialEq; dedup stays in pi ``` - The streaming channel becomes `UnboundedSender<Snapshot>` end-to-end (through the session manager and both callers). HTTP passes a detached channel and ignores it. - pi emits `Text` when the assistant message carries text, else `Thinking` with the **raw** thinking text — no emoji, no trim. - The `💭` prefix and the tail-trim (`preview()` + the char-limit constant) move into the Telegram interface, which renders `Text` as-is and `Thinking` via `preview()`. ## Acceptance criteria - [ ] `Snapshot { Text, Thinking }` defined in the pi module; snapshot channel retyped end-to-end. - [ ] pi no longer contains the `💭` prefix or any Telegram-derived char cap; dedup of consecutive identical snapshots stays in pi. - [ ] The Telegram interface owns the thinking preview (emoji + tail bound); streamed text and the thinking→text flip behave exactly as before. - [ ] HTTP path still returns the authoritative final answer, unaffected. - [ ] pi stream-parsing tests updated for the typed snapshots; `just check` green. ## Blocked by None - can start immediately.
Author
Owner

Implemented typed snapshot refactor (commit dff9573 on branch sandcastle/issue-32).

Key changes:

  • Defined pub enum Snapshot { Text(String), Thinking(String) } (with PartialEq) in pi module
  • Streaming channel retyped to UnboundedSender end-to-end (pi, session, telegram, http)
  • Pi emits raw Text/Thinking variants — no emoji prefix, no length trim in the transport
  • 💭 prefix and 3800-char tail-trim moved to telegram/mod.rs as thinking_preview()
  • Pi stream-parsing tests updated for typed Snapshot variants
  • test_thinking_preview_tail_bounded replaced by test_thinking_emits_raw_text_without_trim_or_emoji
  • 3 new unit tests for thinking_preview() in telegram module

Cannot push to forge (SSH port 22 refused in this sandbox); CI pending push.

Implemented typed snapshot refactor (commit dff9573 on branch sandcastle/issue-32). Key changes: - Defined `pub enum Snapshot { Text(String), Thinking(String) }` (with PartialEq) in pi module - Streaming channel retyped to UnboundedSender<Snapshot> end-to-end (pi, session, telegram, http) - Pi emits raw Text/Thinking variants — no emoji prefix, no length trim in the transport - 💭 prefix and 3800-char tail-trim moved to telegram/mod.rs as `thinking_preview()` - Pi stream-parsing tests updated for typed Snapshot variants - test_thinking_preview_tail_bounded replaced by test_thinking_emits_raw_text_without_trim_or_emoji - 3 new unit tests for thinking_preview() in telegram module Cannot push to forge (SSH port 22 refused in this sandbox); CI pending push.
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#32
No description provided.