Six fixes for the wave-7 picker/input cluster:
DeepSeek -> "Deepseek") and left the gemini- branch's words lowercase
("Gemini 2.5 pro"). Vendor casing + parameter counts now applied after
title-case (GLM, DeepSeek, MiniMax, OpenAI, ERNIE, MiMo, BGE, VL, IT,
FP8, AI; 8b -> 8B, a3b -> A3B), and the gemini branch title-cases like
every other branch.
and was unreachable by keyboard (rows are highlighted, never DOM-focused,
so Radix's own ArrowRight never fires). The chevron is now visible on
every model row and ArrowRight (caret parked at query end) hands focus
to the highlighted trigger and opens its sub; ArrowLeft returns focus
to the search field. Consolidates #86968 + #104532.
-fast/-thinking/-preview ids to the base label. The tag now rides the
display name on every surface, and formatModelPillLabel no longer
doubles Fast for a -fast variant id.
all MoA presets were disabled: manual picks are sticky by design
(d595e636c8), but the virtual moa provider's catalog row disappears
entirely once no preset is enabled, so that one absence is
authoritative (moaPickRemoved) and the pick reseeds from the profile
default. Narrow moa-only exception — no general catalog diff.
token (nimb -> nimb*); none of the CJK routes can honour it (bigram and
trigram routes quote tokens so the star matches literally; LIKE has no
star wildcard at all), so CJK searches returned zero results. The star
is now stripped per token on the CJK path only.
measure() effect deps (stale measurements after toggling Inbox style)
and the card estimate undershot the four-line/wrapped-title worst case
(74px), painting rows over their neighbours on cold start. Card
estimate raised to the worst-case-covering 96px and the deps fixed.
94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
"""CJK search must survive the prefix wildcard callers append (#90636).
|
|
|
|
The web/desktop search endpoint turns every unquoted token into ``token*`` so
|
|
partial English words match. None of the CJK routes can honour that star: the
|
|
bigram and trigram routes quote each token before ``MATCH`` (so ``*`` is matched
|
|
literally) and the LIKE route has no ``*`` wildcard at all (only ``%``/``_``).
|
|
Left in place, every CJK search typed into the desktop/web search box becomes
|
|
a search for a term ending in a literal asterisk and returns nothing, while
|
|
the identical query without the star returns rows.
|
|
|
|
Runs against a real SessionDB in a temp HERMES_HOME, on the trigram and LIKE
|
|
routes only — no ``cjk_unicode61`` tokenizer toolchain is required.
|
|
"""
|
|
|
|
from hermes_state import SessionDB
|
|
|
|
TWO_CHAR = "秃发" # 2 CJK chars — below the trigram threshold, LIKE route
|
|
FOUR_CHAR = "秃发应对" # 4 CJK chars — trigram-eligible
|
|
|
|
|
|
def make_db(tmp_path):
|
|
database = SessionDB(db_path=tmp_path / "state.db")
|
|
session_id = "20260820_000001_cjk001"
|
|
database.create_session(session_id, "cli")
|
|
database.append_message(session_id, "user", "关于秃发应对的讨论内容,请总结")
|
|
database.append_message(session_id, "assistant", "hello nimby world")
|
|
return database
|
|
|
|
|
|
def hits(database, query):
|
|
return database.search_messages(query=query, limit=10, fields=("session_id", "snippet"))
|
|
|
|
|
|
def test_trailing_star_matches_the_bare_query(tmp_path):
|
|
"""The star must widen or keep the result set, never empty it."""
|
|
database = make_db(tmp_path)
|
|
try:
|
|
for term in (TWO_CHAR, FOUR_CHAR):
|
|
bare = hits(database, term)
|
|
starred = hits(database, term + "*")
|
|
assert bare, f"{term!r} should match the seeded message"
|
|
assert len(starred) == len(bare), (
|
|
f"{term + '*'!r} returned {len(starred)} rows vs {len(bare)} for {term!r} — "
|
|
"the caller-appended prefix wildcard is being matched literally"
|
|
)
|
|
finally:
|
|
database.close()
|
|
|
|
|
|
def test_star_is_stripped_per_token_in_boolean_queries(tmp_path):
|
|
"""A multi-token CJK OR query keeps working with a wildcard per token."""
|
|
database = make_db(tmp_path)
|
|
try:
|
|
assert hits(database, "秃发* OR 桂林*")
|
|
finally:
|
|
database.close()
|
|
|
|
|
|
def test_ascii_prefix_wildcard_still_works(tmp_path):
|
|
"""The normalization is CJK-only; the ASCII prefix search is untouched."""
|
|
database = make_db(tmp_path)
|
|
try:
|
|
assert hits(database, "nimb*")
|
|
finally:
|
|
database.close()
|
|
|
|
|
|
def test_a_lone_star_is_not_turned_into_a_match_all(tmp_path):
|
|
"""Stripping must not leave an empty term that matches every row."""
|
|
database = make_db(tmp_path)
|
|
try:
|
|
assert hits(database, "*") == []
|
|
finally:
|
|
database.close()
|
|
|
|
|
|
def test_quoted_cjk_phrase_survives_the_star(tmp_path):
|
|
"""The quoted workaround from the report still matches once starred."""
|
|
database = make_db(tmp_path)
|
|
try:
|
|
assert hits(database, '"秃发"' + "*")
|
|
assert hits(database, '"秃发"')
|
|
finally:
|
|
database.close()
|
|
|
|
|
|
def test_mixed_cjk_and_ascii_query_survives_the_star(tmp_path):
|
|
database = make_db(tmp_path)
|
|
try:
|
|
found = hits(database, "秃发* nimby*")
|
|
assert found
|
|
finally:
|
|
database.close()
|