Skip to content

feat: include reply/quote context in Claude prompt - #194

Open
timurvafin wants to merge 1 commit into
overwirehq:mainfrom
timurvafin:feat/include-quote-in-prompt
Open

timurvafin wants to merge 1 commit into
overwirehq:mainfrom
timurvafin:feat/include-quote-in-prompt

Conversation

@timurvafin

Copy link
Copy Markdown

Summary

When a user replies to a message (especially with a highlighted fragment — Telegram's partial-quote feature, Bot API 7.0+), the bot was reading only update.message.text and dropping the quoted context. Claude then had to guess what the user was referring to.

This PR extracts the quoted fragment and prepends it to the user's new text as a markdown blockquote, so Claude sees both the fragment and the response in a single prompt.

Before vs after

Before:

User (replying with quote on Claude's earlier message): "а каково его население?"
  → prompt sent to Claude: "а каково его население?"
  → Claude: "its what? please clarify"

After:

User (replying with quote on "Столица Франции — Париж."): "а каково его население?"
  → prompt sent to Claude:
    > Столица Франции — Париж.

    а каково его население?
  → Claude: "Население Парижа — около 2,1 млн человек…"

Design

  • Priority: message.quote.text (partial quote, Bot API 7.0+) wins over the full reply_to_message.text. If the user highlighted a fragment, that's what they mean.
  • Fallback: If there's no partial quote, use the full replied-to message. If that message is media, use its caption.
  • Format: markdown blockquote (> line\n> line\n\ntext), natural for Claude.
  • No changes when there's no reply/quote — behaviour is identical.
  • Shared helper in src/bot/utils/quote_prompt.py — both agentic_text and classic handle_text go through it, so classic mode gets the feature for free.

Changes

  • src/bot/utils/quote_prompt.py — new build_user_prompt(message) -> str helper with priority logic and markdown-blockquote rendering.
  • src/bot/orchestrator.pyagentic_text uses build_user_prompt(update.message) instead of update.message.text.
  • src/bot/handlers/message.pyhandle_text_message (classic) same wiring; .pdf unaffected.
  • tests/unit/test_bot/test_quote_prompt.py — 10 tests: plain/reply/partial-quote priority/multiline/media-caption/edge cases (no-text, no-reply, empty user text).

Live verification

Reply via Telegram client with highlighted fragment of Claude's previous answer; bot's database prompt now includes the blockquote; Claude's reply is contextually correct.

Test plan

  • make test — 540 passed (10 new)
  • black/isort/flake8 clean
  • Live smoke: replied to a bot message with a follow-up question whose only referent was the quoted fragment. Claude resolved the reference correctly.

🤖 Generated with Claude Code

When a user replies to a message (especially with a highlighted
fragment — Telegram's partial-quote feature, Bot API 7.0+), the bot
previously read only `update.message.text` and dropped the quoted
context, so Claude had to guess what the user was referring to.

This PR extracts the quoted fragment (partial quote has priority
over the full replied-to message) and prepends it to the user's
new text as a markdown blockquote::

    > quoted fragment line 1
    > quoted fragment line 2

    new user text

Works for both agentic_text and classic handle_text via a shared
helper `src/bot/utils/quote_prompt.build_user_prompt`. Falls back to
plain `message.text` when there's no reply/quote, preserving existing
behaviour.

Also handles replies to media (uses `caption` when `text` is absent)
and guards against MagicMock attributes in unit-test fixtures.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@RichardAtCT RichardAtCT left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice change — small, well tested, and wired the same way in both modes. Tests and lint pass.

One thing before I merge. The quoted text goes into the prompt as a bare markdown blockquote, with nothing telling Claude where it came from (src/bot/utils/quote_prompt.py:38).

In a group, the replied-to message can come from anyone, not just an allowed user. Please add a short label, for example "Quoted message (reference only):", so Claude treats it as material to read rather than instructions to follow.

One line. Then I will merge.

@FrundlesTian

Copy link
Copy Markdown
Collaborator

Hi @timurvafin — I prepared the small follow-up requested in the review:

  • Prefix quoted context with Quoted message (reference only):.
  • Update the existing quote-prompt tests for the labeled output, including the quote-only case.

The commit is based directly on the current PR HEAD (7035eb7) and contains no unrelated changes:

FrundlesTian@f16ef49

It can be applied with:

git fetch https://github.com/FrundlesTian/claude-code-telegram.git fix/pr-194-quote-label
git cherry-pick f16ef49431a67fba503731f7846d9c9346ba475e

Verification: all 540 tests pass; Black, isort, flake8, and mypy are clean.

@FrundlesTian

Copy link
Copy Markdown
Collaborator

Hi @RichardAtCT — quick review update: I prepared a single-commit patch for the outstanding request to label quoted content as reference-only context, including updates to all existing quote-prompt tests.

The patch is based directly on the current PR HEAD (7035eb7):
FrundlesTian@f16ef49

All 540 tests pass, and Black, isort, flake8, and mypy are clean. The PR branch itself has not been updated yet; it is currently waiting for @timurvafin to cherry-pick the patch. Once applied, it should address the remaining review request.

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