refactor(fs): minimize and cap search card meta; keep TUI byte-identical

Address the review of the search render card:

- The search result view carries no `content`: it was a no-op for every
  consumer and serialized the whole search text twice. A UI without a search
  card falls back to the raw tool/result content; the TUI stays byte-identical
  to the pre-search-card generic fallback.
- Bound the serialized presentationMeta with a configurable searchMetaMaxBytes
  (default 64 KiB): the inline item cap does not bound bytes, and spill-policy
  only shrinks content, never meta. capMetaBytes drops trailing groups/paths.
- Share one retention pass (retainGrepMatches/retainGlobPaths in search-core)
  between the model-facing render and the meta projection; remove the second
  cap/preview implementation and the presentation<->grep module cycle by
  moving GrepMatch/previewLine to search-core.
- Rename the result-view discriminant kind -> shape so it no longer collides
  with GenericCallView.kind (ToolCallKind, whose values include 'search').
- Narrow the entry export surface to consumed symbols.
- Sync the three bilingual ToolResultView doc pairs and the Agent Note pair;
  document the deliberate empty-card acceptance vs diffsFromMeta.
- Regenerate config/tool/cordis catalogs for the new config field.
This commit is contained in:
Chinesezjc
2026-07-30 21:57:49 +08:00
parent 74060dfb86
commit 7b6f33f872
23 changed files with 403 additions and 228 deletions

View File

@@ -389,7 +389,15 @@ export class ToolCardComponent implements Component {
const glyph = this.result === undefined ? '○' : '●'
const rawBody = this.renderBody()
const view = this.resultView ?? this.callView
const genericContent = view.card === 'generic' ? view.content ?? this.result?.content : undefined
// A search card (grep/glob results) carries no dedicated TUI rendering and no
// result text of its own: it falls back to the same dim Markdown body as a
// generic card, reading the model-facing text from the raw result content.
// Its structured shape is consumed by capable UIs; the TUI stays
// byte-identical to the pre-search-card generic fallback. Terminal and diff
// cards keep their own body branches.
const genericContent = view.card === 'generic'
? view.content ?? this.result?.content
: view.card === 'search' ? this.result?.content : undefined
const unknownXml = this.definition === undefined && genericContent !== undefined
? renderUnknownXml(
displayText(contentText(genericContent)),
@@ -502,7 +510,10 @@ export class ToolCardComponent implements Component {
// rather than under the dim result-output color.
return { prelude: [...hunks, footer], lines: [] }
}
const content = view.content ?? this.result?.content
// A search card carries no result text of its own; only a generic view
// supplies `content`. Both fall back to the raw result content below.
const viewContent = view.card === 'generic' ? view.content : undefined
const content = viewContent ?? this.result?.content
const prelude: string[] = []
const lines: string[] = []
// The presenter title headlines the body now that the header is a fixed