Merge remote-tracking branch 'origin/master' into feat/search-presenter

# Conflicts:
#	docs/config-catalog.md
#	docs/cookbook/adding-a-tool.i18n.yaml
#	docs/cookbook/adding-a-tool.md
#	docs/cookbook/adding-a-tool.zh.md
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/tools.i18n.yaml
#	docs/core-data-structures/tools.md
#	docs/core-data-structures/tools.zh.md
#	docs/event-producer-consumer.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/core/tools/README.i18n.yaml
#	packages/core/tools/README.md
#	packages/core/tools/README.zh.md
#	packages/core/tools/src/index.ts
#	packages/core/tools/src/presentation.ts
#	packages/fs/tool-fs-search/src/glob.ts
#	packages/fs/tool-fs-search/src/index.ts
#	packages/ui/tui/src/components/transcript.ts
#	packages/ui/tui/tests/tui.spec.ts
This commit is contained in:
Chinesezjc
2026-07-31 11:31:32 +08:00
946 changed files with 28921 additions and 4610 deletions

View File

@@ -389,18 +389,27 @@ export class ToolCardComponent implements Component {
const glyph = this.result === undefined ? '○' : '●'
const rawBody = this.renderBody()
const view = this.resultView ?? this.callView
// 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'
// A generic card's own content, or a search/web card's fallback to the raw
// result content (neither the `search` nor the `web` view carries a `content`
// copy), all render as one dim Markdown block below, so links/lists/headings
// keep the unified dim styling rather than reading as bare text. A search card
// thus stays byte-identical to the pre-search-card generic fallback. Terminal
// and diff cards own their body styling, so they are excluded (mirrors
// renderBody's post-terminal/diff fallback).
const markdownContent = view.card === 'generic'
? view.content ?? this.result?.content
: view.card === 'search' ? this.result?.content : undefined
const unknownXml = this.definition === undefined && genericContent !== undefined
: view.card === 'search'
? this.result?.content
: view.card === 'web'
// A web resultView is only assigned alongside this.result (the result
// handler sets both) and the pending callView is never a web card, so
// the optional-chain undefined side is unreachable here.
/* v8 ignore next */
? this.result?.content
: undefined
const unknownXml = this.definition === undefined && markdownContent !== undefined
? renderUnknownXml(
displayText(contentText(genericContent)),
displayText(contentText(markdownContent)),
this.maxOutputLines,
this.visibility === 'expanded',
displayText,
@@ -413,7 +422,7 @@ export class ToolCardComponent implements Component {
// A generic card renders title and result as one Markdown document, so the
// document's own block spacing is preserved, then dims every row — the whole
// card body reads as one dim block under the status-colored header.
const body = unknownXml ?? (genericContent !== undefined && rawBody.lines.length > 0
const body = unknownXml ?? (markdownContent !== undefined && rawBody.lines.length > 0
? this.dimBody(rawBody, width)
: [...rawBody.prelude, ...rawBody.lines])
const visibleBody = unknownXml !== undefined || this.visibility === 'expanded'
@@ -510,10 +519,11 @@ export class ToolCardComponent implements Component {
// rather than under the dim result-output color.
return { prelude: [...hunks, footer], lines: [] }
}
// 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
// Neither a search card nor a web card carries a `content` copy, so those
// result views fall back to the raw result content here (`view.card ===
// 'generic'` narrows the generic union arm; a search or web card takes the
// same fallback, mirroring the `markdownContent` selection in render()).
const content = (view.card === 'generic' ? view.content : undefined) ?? this.result?.content
const prelude: string[] = []
const lines: string[] = []
// The presenter title headlines the body now that the header is a fixed