|
|
@@ -20,6 +20,8 @@ That list is the one the model reads as long as nothing downstream of the tool r
|
|
|
|
|
|
`CHAT_WEB_MAX_SOURCES` and the primitive's `DEFAULT_WEB_MAX_SOURCES` are removed: with scroll, the chat row and the details panel show the same full list, differentiated only by their container height. `<li value={ordinal}>` still pins each source's 1-based citation index; without the collapse gap the ordinals are now simply contiguous.
|
|
|
|
|
|
+Making the list a scroll container also makes its `padding-left` a correctness constraint, not spacing. A scroll container clips inline-start overflow and offers no way to scroll it back, and `::marker` is right-aligned to the content edge, so a marker wider than the padding silently loses its leading digits — at the list's 20px the two-digit markers rendered as `0.` and `1.` where `10.` and `11.` belonged. `searchMaxResults` is an unbounded positive integer, so the padding is sized in `em` against the list's own font — the one a marker inherits — to hold a three-digit marker (`999. ` measures 2.35em in the app font stack) and keeps the gap the one-digit case already had.
|
|
|
+
|
|
|
## Alternatives considered
|
|
|
|
|
|
**Raise `searchMaxResults` (or make it unbounded) so more sources reach both the model and the card.** Rejected by the user: it changes model-side behavior (more sources into every request's context, more tokens) and widens the gap between what the model reads and what the card draws. The instruction was explicit — keep the cap and the truncation, add a scrollbar.
|
|
|
@@ -36,7 +38,7 @@ Every source the tool returned is always in the DOM, so no source the view carri
|
|
|
|
|
|
`packages/client/ui-primitives/tests/web-block.spec.tsx` drops the collapse cases (head/tail slice, expand-on-click, collapsed-tail numbering, expander-out-of-numbering, head-alone, default cap) and adds: a 30-source card renders all 30 `<li>` with no `[aria-expanded]` and no `<button>`, every `<ol>` child is a source `<li>`, and `<li value>` numbers 1..N contiguously. `packages/client/ui-conversation/tests/web-card.spec.tsx` drops the `CHAT_WEB_MAX_SOURCES` cap assertion; the WebRow expansion test still asserts the card shows every source field. The `packages/web/tool-web` tests are unchanged — the model side did not move.
|
|
|
|
|
|
-jsdom resolves no CSS Modules layout, so it reports `scrollHeight === clientHeight` for every element and cannot witness the scroll at all. The geometry is pinned in the assembled browser instead, by `apps/web/tests/web-search-round.e2e.ts`: its deterministic search double returns 12 provider results, each with a title, a citation snippet, and a date. That first pins the seam's cap end to end in a real composition — the shipped `searchMaxResults` keeps 8, the model-visible render text carries the 8 kept titles and none of the 4 dropped URLs plus `(Showing the first 8 sources. Refine the query for more.)`, and `meta.truncated` is true. A case after the aria golden then expands the `web_search` row and asserts on the card's `<ol>`: 8 `<li>`, no `<button>` anywhere in the card, the `来源列表已截断` indicator visible, and computed `max-height: 320px` with `overflow-y: auto` over `scrollHeight` 574 against `clientHeight` 320. Neither the recorded stream nor the aria golden moved: replay is a positional cursor over the fixture's `assistant/chunk` entries and the search double is a separate local endpoint the provider reaches by `fetch`, while the card is collapsed at capture time so its `<ol>` is out of the DOM and the summary row carries no source count.
|
|
|
+jsdom resolves no CSS Modules layout, so it reports `scrollHeight === clientHeight` for every element and cannot witness the scroll at all. The geometry is pinned in the assembled browser instead, by `apps/web/tests/web-search-round.e2e.ts`: its deterministic search double returns 12 provider results, each with a title, a citation snippet, and a date. That first pins the seam's cap end to end in a real composition — the shipped `searchMaxResults` keeps 8, the model-visible render text carries the 8 kept titles and none of the 4 dropped URLs plus `(Showing the first 8 sources. Refine the query for more.)`, and `meta.truncated` is true. A case after the aria golden then expands the `web_search` row and asserts on the card's `<ol>`: 8 `<li>`, no `<button>` anywhere in the card, the `来源列表已截断` indicator visible, and computed `max-height: 320px` with `overflow-y: auto` over `scrollHeight` 574 against `clientHeight` 320. A further case measures a `999. ` marker in the list's own inherited font and requires the computed `padding-left` to be at least that wide, so the marker room the scroll container cannot clip back is pinned against the widest marker rather than against one fixture's source count. Neither the recorded stream nor the aria golden moved: replay is a positional cursor over the fixture's `assistant/chunk` entries and the search double is a separate local endpoint the provider reaches by `fetch`, while the card is collapsed at capture time so its `<ol>` is out of the DOM and the summary row carries no source count.
|
|
|
|
|
|
## Related
|
|
|
|