fix(web-search-card): surface truncation recovery, widen cardless fallback, validate wire shape, fix tail-cap
Address the ds-review-bot findings on the search card: - searchCardModel dropped the result view's `content`, so a capped search's `Full … stored at: <locator>` recovery footer vanished from the UI (the card replaces the raw text). Thread it through as `SearchCardModel.recovery` and render it below the card at all three sites, only when truncated. - SearchRow's fallback body was gated on `state === 'error'`, so a settled non-error call with no card (a successful nested run_code sub-dispatch, a legacy generic result) showed only its summary with content lost. Widen it to any settled call with `search === null`. - searchCardModel trusted the `files`/`paths` shape the host wire schema only string-checks; a malformed known-kind frame would crash SearchBlock. Validate the full shape and fall to the generic path on mismatch. - SearchBlock's restored tail file header added a row without consuming a tail slot, exceeding maxLines by one and overstating the hidden count. Make it consume a slot so the visible count holds at maxLines and `hidden` stays exact. Correct the fixture JSDoc (now genuinely exceeds the row cap) and the Agent Note recovery-text claim, sync the ui-conversation bilingual README with the search row, and add an assembled keyless snapshot (apps/web/tests/search-card.snapshot.ts) that pins the grep card's shape from the built bundles.
This commit is contained in:
@@ -159,6 +159,15 @@ const SEARCH_MATCHES_FIXTURE: { path: string; matches: { lineNumber: number; lin
|
||||
{ lineNumber: 60, line: 'export function searchCardModel(block: ToolCallBlock): SearchCardModel | null {' },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'packages/client/ui-conversation/src/client/toolviews/search-row.tsx',
|
||||
matches: [
|
||||
{ lineNumber: 71, line: 'export function SearchRow({ toolName, block }: ToolRowProps) {' },
|
||||
{ lineNumber: 73, line: ' const search = searchCardModel(block)' },
|
||||
{ lineNumber: 90, line: ' <SearchBlock {...search.card} maxLines={CHAT_SEARCH_MAX_LINES} className={css.search} />' },
|
||||
{ lineNumber: 113, line: " ctx.slots.register({ name: 'conversation.chat.toolview', key: 'grep' }, SearchRow)" },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -169,7 +178,7 @@ const SEARCH_MATCHES_FIXTURE: { path: string; matches: { lineNumber: number; lin
|
||||
* `Line N:` rows, then a spill-recovery footer.
|
||||
*/
|
||||
const SEARCH_MATCHES_TEXT = [
|
||||
'Found 5 of 42 matches',
|
||||
'Found 9 of 42 matches',
|
||||
'',
|
||||
...SEARCH_MATCHES_FIXTURE.map(file =>
|
||||
[file.path, ...file.matches.map(m => `Line ${m.lineNumber}: ${m.line}`)].join('\n')),
|
||||
|
||||
Reference in New Issue
Block a user