feat(core): display doc title with display-config for semantic result (#13194)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Improved document title display in AI chat semantic search results by
fetching titles from a dedicated service for more accurate and
consistent information.

* **Enhancements**
* Enhanced integration between chat and document display features,
ensuring configuration and services are consistently passed through chat
components for better user experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Wu Yue <akumatus@gmail.com>
This commit is contained in:
Cats Juice
2025-07-14 15:58:17 +08:00
committed by GitHub
parent d05bb9992c
commit 3948b8eada
5 changed files with 25 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ import {
EdgelessEditorActions,
PageEditorActions,
} from '../../_common/chat-actions-handle';
import type { DocDisplayConfig } from '../../components/ai-chat-chips';
import {
type ChatMessage,
type ChatStatus,
@@ -82,6 +83,9 @@ export class ChatMessageAssistant extends WithDisposable(ShadowlessElement) {
@property({ attribute: false })
accessor independentMode: boolean | undefined;
@property({ attribute: false })
accessor docDisplayService!: DocDisplayConfig;
get state() {
const { isLast, status } = this;
return isLast
@@ -141,6 +145,7 @@ export class ChatMessageAssistant extends WithDisposable(ShadowlessElement) {
.affineFeatureFlagService=${this.affineFeatureFlagService}
.notificationService=${this.notificationService}
.theme=${this.affineThemeService.appTheme.themeSignal}
.docDisplayService=${this.docDisplayService}
></chat-content-stream-objects>`;
}

View File

@@ -417,6 +417,7 @@ export class AIChatContent extends SignalWatcher(
.width=${this.width}
.independentMode=${this.independentMode}
.messages=${this.messages}
.docDisplayService=${this.docDisplayConfig}
></ai-chat-messages>
<ai-chat-composer
style=${styleMap({

View File

@@ -20,6 +20,7 @@ import { AffineIcon } from '../../_common/icons';
import { AIPreloadConfig } from '../../chat-panel/preload-config';
import { type AIError, AIProvider, UnauthorizedError } from '../../provider';
import { mergeStreamObjects } from '../../utils/stream-objects';
import type { DocDisplayConfig } from '../ai-chat-chips';
import { type ChatContextValue } from '../ai-chat-content/type';
import type {
AINetworkSearchConfig,
@@ -202,6 +203,9 @@ export class AIChatMessages extends WithDisposable(ShadowlessElement) {
@property({ attribute: false })
accessor width: Signal<number | undefined> | undefined;
@property({ attribute: false })
accessor docDisplayService!: DocDisplayConfig;
@query('.chat-panel-messages-container')
accessor messagesContainer: HTMLDivElement | null = null;
@@ -328,6 +332,7 @@ export class AIChatMessages extends WithDisposable(ShadowlessElement) {
.retry=${() => this.retry()}
.width=${this.width}
.independentMode=${this.independentMode}
.docDisplayService=${this.docDisplayService}
></chat-message-assistant>`;
} else if (isChatAction(item) && this.host) {
return html`<chat-message-action

View File

@@ -13,6 +13,7 @@ import { css, html, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import type { AffineAIPanelState } from '../../widgets/ai-panel/type';
import type { DocDisplayConfig } from '../ai-chat-chips';
import type { StreamObject } from '../ai-chat-messages';
export class ChatContentStreamObjects extends WithDisposable(
@@ -54,6 +55,9 @@ export class ChatContentStreamObjects extends WithDisposable(
@property({ attribute: false })
accessor notificationService!: NotificationService;
@property({ attribute: false })
accessor docDisplayService!: DocDisplayConfig;
private renderToolCall(streamObject: StreamObject) {
if (streamObject.type !== 'tool-call') {
return nothing;
@@ -178,6 +182,7 @@ export class ChatContentStreamObjects extends WithDisposable(
return html`<doc-semantic-search-result
.data=${streamObject}
.width=${this.width}
.docDisplayService=${this.docDisplayService}
></doc-semantic-search-result>`;
case 'doc_keyword_search':
return html`<doc-keyword-search-result

View File

@@ -5,6 +5,8 @@ import type { Signal } from '@preact/signals-core';
import { html, nothing } from 'lit';
import { property } from 'lit/decorators.js';
import type { DocDisplayConfig } from '../ai-chat-chips';
interface DocSemanticSearchToolCall {
type: 'tool-call';
toolCallId: string;
@@ -58,6 +60,9 @@ export class DocSemanticSearchResult extends WithDisposable(ShadowlessElement) {
@property({ attribute: false })
accessor width: Signal<number | undefined> | undefined;
@property({ attribute: false })
accessor docDisplayService!: DocDisplayConfig;
renderToolCall() {
return html`<tool-call-card
.name=${`Finding semantically related pages for "${this.data.args.query}"`}
@@ -75,7 +80,10 @@ export class DocSemanticSearchResult extends WithDisposable(ShadowlessElement) {
.icon=${AiEmbeddingIcon()}
.width=${this.width}
.results=${this.data.result
.map(result => parseResultContent(result.content))
.map(result => ({
...parseResultContent(result.content),
title: this.docDisplayService.getTitle(result.docId),
}))
.filter(Boolean)}
></tool-result-card>`;
}