Skip to content

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

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

feat: include reply/quote context in Claude prompt#194
timurvafin wants to merge 1 commit intoRichardAtCT: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>
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.

1 participant