Skip to content

Commit c63b44a

Browse files
author
SunCode
committed
fix: 移除 InlineCallTrace 中间文本渲染,避免流式回复文字重复
- 删除 InlineCallTrace 中 intermediate text 的展示逻辑 - 移除对应的 CSS 样式 - AssistantMessage.vue 改为始终显示主内容区 - 解决流式回复时文字重复渲染的问题
1 parent 47599f0 commit c63b44a

2 files changed

Lines changed: 4 additions & 88 deletions

File tree

src/renderer/components/chat/AssistantMessage.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ async function copyContent() {
168168
</div>
169169
</details>
170170

171-
<!-- Visible reply text: during streaming, show only when InlineCallTrace
172-
is empty (avoid double-rendering the current text block);
173-
after streaming, always show. -->
171+
<!-- Visible reply text: always render the assistant's answer in the main
172+
content area. The streaming InlineCallTrace only shows process
173+
entries (thinking / tools / guidance), so text is not double-rendered. -->
174174
<div
175-
v-if="hasContent && (!message.isStreaming || !hasInlineTrace)"
175+
v-if="hasContent"
176176
class="message-content"
177177
:class="{ streaming: message.isStreaming }"
178178
>

src/renderer/components/chat/InlineCallTrace.vue

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { buildSubagentInlineTrace, type InlineCallTraceEntry } from './call-trac
88
import StreamingText from './StreamingText.vue';
99
1010
const INLINE_TEXT_LIMIT = 80;
11-
const INTERMEDIATE_PREVIEW_LIMIT = 120;
1211
1312
const props = withDefaults(
1413
defineProps<{
@@ -161,16 +160,6 @@ function emptyOutputLabel(): string {
161160
return props.uiLanguage === 'en' ? 'No output yet' : '暂无输出';
162161
}
163162
164-
// One-line preview for intermediate (non-final) model text blocks streamed
165-
// between tool calls. The UI exists to show the overall run logic, so long
166-
// intermediate narration is collapsed to a single line and expandable on demand.
167-
function intermediatePreview(text: string): string {
168-
const firstLine = (text.trim().split('\n')[0] ?? '').trim();
169-
const collapsed = firstLine.replace(/\s+/g, ' ');
170-
if (collapsed.length <= INTERMEDIATE_PREVIEW_LIMIT) return collapsed;
171-
return `${collapsed.slice(0, INTERMEDIATE_PREVIEW_LIMIT)}…`;
172-
}
173-
174163
// ── subagent helpers ──
175164
176165
function subResultTrace(result: SubagentResult, isStreaming: boolean) {
@@ -222,27 +211,6 @@ function streamingToolClass(entry: InlineCallTraceEntry): string {
222211
<StreamingText :text="entry.text" :is-streaming="isStreaming && entry.isActive" />
223212
</div>
224213

225-
<!-- Previous text entries: intermediate model output, collapsed to a one-line preview -->
226-
<details
227-
v-else-if="entry.kind === 'text' && !entry.isCurrent"
228-
class="streaming-intermediate-details"
229-
>
230-
<summary class="streaming-intermediate-summary">
231-
<span class="streaming-intermediate-preview">{{ intermediatePreview(entry.text) }}</span>
232-
</summary>
233-
<div class="streaming-intermediate-full">
234-
<StreamingText :text="entry.text" :is-streaming="false" />
235-
</div>
236-
</details>
237-
238-
<div
239-
v-else-if="entry.kind === 'text' && entry.isCurrent"
240-
class="streaming-process-text streaming-live-text"
241-
:class="{ active: entry.isActive }"
242-
>
243-
<StreamingText :text="entry.text" :is-streaming="isStreaming" />
244-
</div>
245-
246214
<!-- Mid-run guidance: shown inline (no standalone user bubble) -->
247215
<div
248216
v-else-if="entry.kind === 'guidance'"
@@ -480,58 +448,6 @@ function streamingToolClass(entry: InlineCallTraceEntry): string {
480448
color: var(--color-text);
481449
}
482450
483-
/* Intermediate (non-final) model text between tool calls: collapsed to a
484-
one-line preview, expandable to read the full narration. */
485-
.streaming-intermediate-details {
486-
min-width: 0;
487-
}
488-
489-
.streaming-intermediate-summary {
490-
display: flex;
491-
align-items: baseline;
492-
gap: 6px;
493-
max-width: 100%;
494-
cursor: pointer;
495-
list-style: none;
496-
font-size: 13px;
497-
line-height: 1.6;
498-
color: var(--color-text-muted);
499-
padding: 1px 0;
500-
}
501-
502-
.streaming-intermediate-summary::-webkit-details-marker {
503-
display: none;
504-
}
505-
506-
.streaming-intermediate-summary::before {
507-
content: '';
508-
flex: 0 0 auto;
509-
font-family: var(--font-mono);
510-
font-size: 10px;
511-
color: currentColor;
512-
opacity: 0.6;
513-
transition: transform 0.15s;
514-
}
515-
516-
.streaming-intermediate-details[open] > .streaming-intermediate-summary::before {
517-
transform: rotate(90deg);
518-
}
519-
520-
.streaming-intermediate-preview {
521-
min-width: 0;
522-
overflow: hidden;
523-
text-overflow: ellipsis;
524-
white-space: nowrap;
525-
}
526-
527-
.streaming-intermediate-full {
528-
margin: 4px 0 6px;
529-
padding: 4px 0;
530-
color: var(--color-text-secondary);
531-
font-size: 14px;
532-
line-height: 1.6;
533-
}
534-
535451
.streaming-tool-details {
536452
min-width: 0;
537453
color: var(--color-text-muted);

0 commit comments

Comments
 (0)