The model picker gets a sort beside its search: name (as before: the one in use first, then A to Z), cheapest first, priciest first. One choice for every kind of model, kept in this browser (havre.msort).
Sorted by price, the price column says which way (an arrow, and aria-sort). A text model goes by its price in, then out (a chat is mostly what's sent in: the card, the memories, the conversation so far), so the arrow sits after IN: $ IN ↑ / OUT. Photos go by their price (then what extra pictures add), voices by the price for a million characters, hearing by the second.
Sorted by price, nothing is held at the top: the model in use stays highlighted where its price puts it.
Clips have no price to sort by (Venice prices each one when asked), so their picker shows no sort.
On a phone the table's heads are hidden; the sort sits under the search, at 16px.
Code: A.modelCost, A.sortModels, A.MODEL_SORTS in abilities.js (pure, unit-tested); app.js sorts with them in renderModels and draws the heads in modelHead().
Tests
node --test tests/*.test.mjs: 101 pass, with a new one for the order.
A focused browser check of the picker against a fake Venice, desktop (1280×800) and phone (375×667): the three orders, the heads, the choice kept through a reload, no sort for clips, photos by price, no sideways scroll and no field under 16px on the phone. Green.
tests/smoke.mjs: new checks for the sort on desktop (run green), the clip picker and the phone.
Note: smoke already fails on gh-pages without this change. First at count(page, "#ablist tr", 8): the ASMR row (#216) made it 9. Then at the voice-note caption: the voice-notes button now cycles off → on → asmr, so the test's click meant to turn them off turns ASMR on. Left for a fix of its own.
**What**
- The model picker gets a sort beside its search: **name** (as before: the one in use first, then A to Z), **cheapest first**, **priciest first**. One choice for every kind of model, kept in this browser (`havre.msort`).
- Sorted by price, the price column says which way (an arrow, and `aria-sort`). A text model goes by its price in, then out (a chat is mostly what's sent in: the card, the memories, the conversation so far), so the arrow sits after IN: `$ IN ↑ / OUT`. Photos go by their price (then what extra pictures add), voices by the price for a million characters, hearing by the second.
- Sorted by price, nothing is held at the top: the model in use stays highlighted where its price puts it.
- Clips have no price to sort by (Venice prices each one when asked), so their picker shows no sort.
- On a phone the table's heads are hidden; the sort sits under the search, at 16px.
**Code**: `A.modelCost`, `A.sortModels`, `A.MODEL_SORTS` in abilities.js (pure, unit-tested); app.js sorts with them in `renderModels` and draws the heads in `modelHead()`.
**Tests**
- `node --test tests/*.test.mjs`: 101 pass, with a new one for the order.
- A focused browser check of the picker against a fake Venice, desktop (1280×800) and phone (375×667): the three orders, the heads, the choice kept through a reload, no sort for clips, photos by price, no sideways scroll and no field under 16px on the phone. Green.
- tests/smoke.mjs: new checks for the sort on desktop (run green), the clip picker and the phone.
- Note: smoke already fails on gh-pages without this change. First at `count(page, "#ablist tr", 8)`: the ASMR row (#216) made it 9. Then at the voice-note caption: the voice-notes button now cycles off → on → asmr, so the test's click meant to turn them off turns ASMR on. Left for a fix of its own.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
havre.msort).aria-sort). A text model goes by its price in, then out (a chat is mostly what's sent in: the card, the memories, the conversation so far), so the arrow sits after IN:$ IN ↑ / OUT. Photos go by their price (then what extra pictures add), voices by the price for a million characters, hearing by the second.Code:
A.modelCost,A.sortModels,A.MODEL_SORTSin abilities.js (pure, unit-tested); app.js sorts with them inrenderModelsand draws the heads inmodelHead().Tests
node --test tests/*.test.mjs: 101 pass, with a new one for the order.count(page, "#ablist tr", 8): the ASMR row (#216) made it 9. Then at the voice-note caption: the voice-notes button now cycles off → on → asmr, so the test's click meant to turn them off turns ASMR on. Left for a fix of its own.