Commit 24aaba2
committed
refactor(web): the browser picker uses core, and stops being the worse one
Both UIs are React, so it is easy to assume they already share what matters.
They did not. The Ink picker called `core/catalog`'s `filterModels` and `rank`
and `core/format`'s helpers; the browser picker reimplemented filtering inline
and skipped the rest. The copy was not merely duplicated, it was WORSE:
filtering core.filterModels vs inline copy, no free-only filter
sorting core.rank (benchmark) vs none — whatever order the registry
happened to return
a free model "free" vs "$0.00/M"
a 1M-context model "1M" vs "1000K"
The "$0.00" case is the one worth pausing on: that file's own header says "a
catalog with no prices shows no prices, rather than '$0.00', which would read as
free" — and eleven lines down it rendered exactly that. The rule was written
once and enforced in one of the two places it applies.
Root cause was a hand-written type. `web/src/api.ts` mirrored `NormalizedModel`
as a narrower `CatalogModel` — id, name, context, pricing, tools — so the
browser could not call `rank`, which sorts on `benchmarks`, a field the server
was already sending and the type simply hid. Same for `CatalogCapabilities`,
whose mirror had silently lost `requiresAuth`. Both are now type-only imports
from `src/ports/`: they erase, cost the bundle nothing, and cannot drift.
Verified in a browser against the live OpenRouter catalog: ranked by benchmark
rather than registry order, "1.1M context" not "1100K", a working free-only
filter (14 of 342), and free models rendering as "free".
What stays local to each UI is presentation, which is the right seam: the
browser keeps `priceLabel`, because `formatPrice` correctly returns "free" and
appending "/M in" to that gives "free/M in", which is not a thing anyone says.
770 tests. Bundle unchanged at 69.6 kB — core is pure and tree-shakes.
Signed-off-by: jellologic <31935831+jellologic@users.noreply.github.com>1 parent 0e47540 commit 24aaba2
2 files changed
Lines changed: 51 additions & 27 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
208 | 208 | | |
209 | 209 | | |
210 | 210 | | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
220 | 226 | | |
221 | 227 | | |
222 | 228 | | |
223 | 229 | | |
224 | | - | |
| 230 | + | |
225 | 231 | | |
226 | 232 | | |
227 | 233 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
5 | 11 | | |
6 | 12 | | |
7 | 13 | | |
| |||
15 | 21 | | |
16 | 22 | | |
17 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
18 | 38 | | |
19 | 39 | | |
20 | 40 | | |
| |||
30 | 50 | | |
31 | 51 | | |
32 | 52 | | |
| 53 | + | |
33 | 54 | | |
34 | 55 | | |
35 | 56 | | |
| |||
44 | 65 | | |
45 | 66 | | |
46 | 67 | | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
58 | 74 | | |
59 | 75 | | |
60 | 76 | | |
| |||
127 | 143 | | |
128 | 144 | | |
129 | 145 | | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
130 | 152 | | |
131 | 153 | | |
132 | 154 | | |
| |||
174 | 196 | | |
175 | 197 | | |
176 | 198 | | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
| 199 | + | |
| 200 | + | |
183 | 201 | | |
184 | 202 | | |
185 | 203 | | |
| |||
0 commit comments