Skip to content

MessageAccumulator.add_messages_for_semantic_ref treats the exclusive TextRange.end as inclusive #372

Open

Description

@KRRT7

collections.py:420:

for message_ordinal in range(message_ordinal_start, message_ordinal_end + 1):

TextRange.end is exclusive: TextLocation.chunk_ordinal in an end is "1 + ordinal of the last chunk". When end.chunk_ordinal == 0, message end.message_ordinal contains none of the range's text, but the loop still adds it. text_range_from_message_range produces exactly these ranges (end=TextLocation(end + 1)).

For example, TextRange(TextLocation(0, 0), TextLocation(1, 0)) covers exactly message 0, as TextRange.__contains__ agrees, but message 1 is also added to the matches.

The function runs on every query path through _accumulate_messages and message_matches_from_knowledge_matches. That includes search_conversation, ConversationBase.query, and the MCP query_conversation. Today it only affects semantic refs whose range has an end. Python ingestion only creates point ranges, so this is reachable through imported or deserialized data.

The TypeScript original loops with messageOrdinal < messageOrdinalEnd. That's also wrong when end.chunk_ordinal > 0, e.g. [(3,0), (3,2)) adds no message at all.

Fix

Include end.message_ordinal only when end.chunk_ordinal > 0:

last = end.message_ordinal if end.chunk_ordinal > 0 else end.message_ordinal - 1
for message_ordinal in range(message_ordinal_start, last + 1):

This adds exactly the messages that hold at least one chunk inside the range, which is what TextRange.__contains__ implies, in both the boundary cases above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions