fix(sessions): match non-ASCII content in AdvancedSQLiteSession search - #4716
fix(sessions): match non-ASCII content in AdvancedSQLiteSession search#4716LeSingh1 wants to merge 2 commits into
Conversation
find_turns_by_content matches the search term against the message_data column with LIKE, but rows are written as json.dumps(item), which escapes every non-ASCII character as \uXXXX. A raw term therefore never matches non-ASCII content: searching a Japanese conversation for a Japanese word returns nothing. Re-encode the term the same way before building the LIKE pattern. ASCII searches are byte-identical to before; non-ASCII ones now match. The same column feeds create_branch_from_content, so that path is fixed too.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 596f1f30b4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
seratch
left a comment
There was a problem hiding this comment.
The JSON encoding fix correctly makes non-ASCII content searchable, but it also makes SQLite LIKE metacharacters in those newly reachable searches active.
For example, a search term containing % or _ can match a different turn than the literal content requested, and create_branch_from_content() can consequently branch from the wrong turn. Please escape %, _, and the chosen escape character in the encoded needle, use an explicit LIKE ... ESCAPE ... clause, and add regression coverage combining non-ASCII text with literal % and _.
The encoded needle went into a bare LIKE, so % and _ in a search term acted as wildcards instead of matching literally. Searching for "50%" matched any turn starting "50", and find_turns_by_content feeds create_branch_from_content, so a branch could be cut from the wrong turn. Escape the escape character first, then % and _, and pair the pattern with an explicit ESCAPE clause.
|
Good catch — done, all three.
Worth noting the wildcard behaviour was there before this PR; what my change did was make it reachable for non-ASCII terms, which is how you spotted it. So the fix covers ASCII terms too — New test combines non-ASCII with literal One thing I got wrong on the first pass and corrected: I had asserted a bare 130 passed in the file. |
seratch
left a comment
There was a problem hiding this comment.
Thanks for addressing the LIKE wildcard escaping. One correctness issue remains: searching for é also matches a message containing the literal text \u00e9. Its stored JSON contains \\u00e9, and the encoded search needle can match starting at the second backslash. Since matching rows are accepted without checking decoded content, create_branch_from_content("é") can select an earlier turn that does not contain é.
Please validate candidate matches against decoded message content and add a regression with an earlier literal-escape turn followed by an actual Unicode turn. Verify that search returns only the actual Unicode turn and that content-based branching uses that turn.
The bug
AdvancedSQLiteSession.find_turns_by_content()never matches non-ASCII content.Session rows are stored with
json.dumps(item), which escapes every non-ASCII character as\uXXXX. The search then does... AND am.message_data LIKE ?with the raw term, so the term and the stored bytes can never line up. A user who stores a Japanese conversation and searches it for a Japanese word gets an empty list, with no error.create_branch_from_content()searches the same column, so it fails the same way — you can't branch from a non-ASCII turn.Repro on main
The fix
Re-encode the search term with
json.dumpsbefore building theLIKEpattern, so it is in the same encoding as the column. ASCII searches are byte-identical to before. This also fixes terms containing"or\, which were escaped in storage but not in the query.With the fix, that test passes and the full file is green:
ruff check,ruff format --checkandmypyare clean on both files.