A crowd you can find, and a phone 65px too narrow
Two reports against 1.6.0 and 1.7.0, both correct. The crowd worked end to end and was, in practice, not there: the picker was behind the ⋯ menu of a chat that already existed, and the switch was a card on the Agents page, which made it read as an agent-chat feature. The picker is now a button in the composer toolbar on both screens that include it, and on the new-chat screen the choice rides along with the first message, so a chat can start as a crowd instead of having to be converted into one. The instance switch has its own page. The width bug was the suggestion cards, exactly as reported. `.suggestions` rendered 455px inside a 366px column, and the tree's standing rule applied on its own made it worse -- 428px to 455px. A grid item carries `min-width: auto`, which is a min-content floor, and a floor beats `width: 100%`; the floor is measured while the percentage is indefinite, so `min(100%, …)` alone sends the track to a card's max-content. Both halves now go on all four auto-fit grids, and a test refuses either alone. It survived four releases of narrow-width checking because the harness never rendered that screen: `TestClient(app)` runs no lifespan outside a `with` block, so the startup-seeded cards were missing from every shot ever taken of it. And its overflow check skipped anything inside a scroller -- right for a table in its own scroller, blind to the scroller itself, which `overflow-y: auto` makes scroll sideways too. Both fixed; it now names the box and the child to blame. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -70,6 +70,87 @@ def _members(db, chat) -> list[str]:
|
||||
]
|
||||
|
||||
|
||||
# --- Reachable where somebody would look --------------------------------------
|
||||
#
|
||||
# The feature shipped in 1.6.0 switched on and unreachable: the only control was
|
||||
# inside the Chat settings panel, behind the ⋯ menu, in a chat that already
|
||||
# existed. The owner enabled it, went looking, and reported that there was nothing
|
||||
# to find. A control nobody can find is a feature nobody has, so these assert the
|
||||
# two places it has to be rather than the one place it was.
|
||||
def test_the_composer_offers_the_crowd_in_a_chat(client, db):
|
||||
"""Beside the tool switches, where the comparable decisions are."""
|
||||
chat = _chat(db)
|
||||
page = client.get(f"/chat/{chat.id}").text
|
||||
assert 'name="crowd_model_ids"' in page
|
||||
assert 'form="crowd-form"' in page
|
||||
assert '<form id="crowd-form">' in page
|
||||
|
||||
|
||||
def test_the_composer_offers_the_crowd_before_the_chat_exists(client, db):
|
||||
"""On the new-chat screen there is no row to attach anybody to, so the choice
|
||||
rides along with the first message — the mechanism the scope switches use."""
|
||||
page = client.get("/chat").text
|
||||
assert 'name="crowd_model_ids"' in page
|
||||
# Riding along, so no sibling form and no PATCH: the composer's own POST
|
||||
# carries it.
|
||||
assert '<form id="crowd-form">' not in page
|
||||
assert 'value="second-model"' in page
|
||||
|
||||
|
||||
def test_starting_a_chat_with_a_crowd_keeps_it(client, db):
|
||||
"""The end of that path: the first message creates the chat *and* its crowd."""
|
||||
from sqlalchemy import select as sa_select
|
||||
|
||||
client.post(
|
||||
"/api/chats/start",
|
||||
data={
|
||||
"content": "Who is right?",
|
||||
"model_id": "main-model",
|
||||
"crowd_model_ids": ["", "second-model", "third-model"],
|
||||
},
|
||||
follow_redirects=False,
|
||||
)
|
||||
db.expire_all()
|
||||
chat = db.scalars(sa_select(Chat).order_by(Chat.created_at.desc())).first()
|
||||
assert [row.model_id for row in sorted(chat.crowd, key=lambda r: r.position)] == [
|
||||
"second-model",
|
||||
"third-model",
|
||||
]
|
||||
|
||||
|
||||
def test_starting_a_chat_refuses_a_model_the_person_cannot_reach(client, db):
|
||||
"""The same rule as the panel, in the same one function, so there is nowhere
|
||||
for the two to disagree."""
|
||||
from sqlalchemy import select as sa_select
|
||||
|
||||
group = Group(name="Wheel")
|
||||
db.add(group)
|
||||
restricted = db.scalar(select(Model).where(Model.model_id == "third-model"))
|
||||
restricted.public = False
|
||||
restricted.groups = [group]
|
||||
user = _user(db)
|
||||
user.role = "user"
|
||||
db.commit()
|
||||
|
||||
client.post(
|
||||
"/api/chats/start",
|
||||
data={
|
||||
"content": "Who is right?",
|
||||
"model_id": "main-model",
|
||||
"crowd_model_ids": ["second-model", "third-model"],
|
||||
},
|
||||
follow_redirects=False,
|
||||
)
|
||||
db.expire_all()
|
||||
chat = db.scalars(sa_select(Chat).order_by(Chat.created_at.desc())).first()
|
||||
assert [row.model_id for row in chat.crowd] == ["second-model"]
|
||||
|
||||
|
||||
def test_the_composer_control_is_absent_while_the_feature_is_off(client, db):
|
||||
settings_store.update(db, {"enabled": False}, key=settings_store.CROWD)
|
||||
assert 'name="crowd_model_ids"' not in client.get("/chat").text
|
||||
|
||||
|
||||
# --- Choosing -----------------------------------------------------------------
|
||||
def test_the_panel_offers_the_other_models(client, db):
|
||||
chat = _chat(db)
|
||||
|
||||
Reference in New Issue
Block a user