fix: adjust sub-agent notice spacing in minimal mode
This commit is contained in:
parent
2700a25702
commit
a5412dae34
@ -23,6 +23,7 @@ export function created() {
|
|||||||
|
|
||||||
export async function mounted() {
|
export async function mounted() {
|
||||||
debugLog('Vue应用已挂载');
|
debugLog('Vue应用已挂载');
|
||||||
|
console.log('[DEBUG_SYSTEM][boot] 前端调试版本已加载 2026-04-05');
|
||||||
if (window.ensureCsrfToken) {
|
if (window.ensureCsrfToken) {
|
||||||
window.ensureCsrfToken().catch((err) => {
|
window.ensureCsrfToken().catch((err) => {
|
||||||
console.warn('CSRF token 初始化失败:', err);
|
console.warn('CSRF token 初始化失败:', err);
|
||||||
|
|||||||
@ -1,6 +1,16 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import { debugLog } from './common';
|
import { debugLog } from './common';
|
||||||
|
|
||||||
|
const SUB_AGENT_DONE_PREFIX_RE = /^(?:✅\s*)?子智能体\s*#?\s*(\d+)\s*任务摘要[::]/;
|
||||||
|
|
||||||
|
function parseSubAgentDoneLabel(rawContent: any): string | null {
|
||||||
|
const content = (rawContent || '').toString().trim();
|
||||||
|
if (!content) return null;
|
||||||
|
const match = content.match(SUB_AGENT_DONE_PREFIX_RE);
|
||||||
|
if (!match || !/已完成/.test(content)) return null;
|
||||||
|
return `子智能体${match[1]} 任务完成`;
|
||||||
|
}
|
||||||
|
|
||||||
export const historyMethods = {
|
export const historyMethods = {
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 关键功能:获取并显示历史对话内容
|
// 关键功能:获取并显示历史对话内容
|
||||||
@ -315,6 +325,41 @@ export const historyMethods = {
|
|||||||
this.messages.push(currentAssistantMessage);
|
this.messages.push(currentAssistantMessage);
|
||||||
currentAssistantMessage = null;
|
currentAssistantMessage = null;
|
||||||
}
|
}
|
||||||
|
if (message.role === 'system') {
|
||||||
|
const rawContent = message.content || '';
|
||||||
|
const label = parseSubAgentDoneLabel(rawContent);
|
||||||
|
console.log('[DEBUG_SYSTEM][history] 命中 role=system 历史消息', {
|
||||||
|
rawContent,
|
||||||
|
matchedSubAgentDone: !!label
|
||||||
|
});
|
||||||
|
if (label) {
|
||||||
|
// 历史中的 system 通知转换为 assistant system action,避免被 role=system 过滤掉
|
||||||
|
this.messages.push({
|
||||||
|
role: 'assistant',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
id: `history-system-${Date.now()}-${Math.random()}`,
|
||||||
|
type: 'system',
|
||||||
|
content: label,
|
||||||
|
variant: 'sub_agent_done',
|
||||||
|
streaming: false,
|
||||||
|
timestamp: Date.now()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
streamingThinking: '',
|
||||||
|
streamingText: '',
|
||||||
|
currentStreamingType: null,
|
||||||
|
activeThinkingId: null,
|
||||||
|
awaitingFirstContent: false,
|
||||||
|
generatingLabel: ''
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('[DEBUG_SYSTEM][history] role=system 被历史加载拦截(非子智能体完成)', {
|
||||||
|
rawContent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
debugLog('处理其他类型消息:', message.role);
|
debugLog('处理其他类型消息:', message.role);
|
||||||
this.messages.push({
|
this.messages.push({
|
||||||
|
|||||||
@ -17,6 +17,17 @@ export const taskPollingMethods = {
|
|||||||
const eventType = event.type;
|
const eventType = event.type;
|
||||||
const eventData = event.data || {};
|
const eventData = event.data || {};
|
||||||
const eventIdx = event.idx;
|
const eventIdx = event.idx;
|
||||||
|
if (
|
||||||
|
eventType === 'system_message' ||
|
||||||
|
eventType === 'sub_agent_waiting' ||
|
||||||
|
(eventType === 'user_message' && eventData?.sub_agent_notice)
|
||||||
|
) {
|
||||||
|
console.log('[DEBUG_SYSTEM][event] 捕获关键事件', {
|
||||||
|
eventType,
|
||||||
|
eventIdx,
|
||||||
|
eventData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 事件去重检查
|
// 事件去重检查
|
||||||
if (typeof eventIdx === 'number') {
|
if (typeof eventIdx === 'number') {
|
||||||
@ -145,6 +156,10 @@ export const taskPollingMethods = {
|
|||||||
this.handleUserMessage(eventData, eventIdx);
|
this.handleUserMessage(eventData, eventIdx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'system_message':
|
||||||
|
this.handleSystemMessage(eventData, eventIdx);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debugLog(`[TaskPolling] 未知事件类型: ${eventType}`);
|
debugLog(`[TaskPolling] 未知事件类型: ${eventType}`);
|
||||||
}
|
}
|
||||||
@ -767,6 +782,20 @@ export const taskPollingMethods = {
|
|||||||
this.conditionalScrollToBottom();
|
this.conditionalScrollToBottom();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleSystemMessage(data: any) {
|
||||||
|
const content = (data?.content || data?.message || '').trim();
|
||||||
|
console.log('[DEBUG_SYSTEM][polling] 收到 system_message 事件', {
|
||||||
|
raw: data,
|
||||||
|
normalizedContent: content,
|
||||||
|
currentConversationId: this.currentConversationId
|
||||||
|
});
|
||||||
|
if (!content) {
|
||||||
|
console.log('[DEBUG_SYSTEM][polling] system_message 内容为空,跳过');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.appendSystemAction(content);
|
||||||
|
},
|
||||||
|
|
||||||
handleTaskError(data: any) {
|
handleTaskError(data: any) {
|
||||||
const shouldRetry = Boolean(data?.retry);
|
const shouldRetry = Boolean(data?.retry);
|
||||||
if (shouldRetry) {
|
if (shouldRetry) {
|
||||||
|
|||||||
@ -16,6 +16,30 @@ import {
|
|||||||
} from '../../composables/usePanelResize';
|
} from '../../composables/usePanelResize';
|
||||||
import { debugLog } from './common';
|
import { debugLog } from './common';
|
||||||
|
|
||||||
|
const SUB_AGENT_DONE_PREFIX_RE = /^(?:✅\s*)?子智能体\s*#?\s*(\d+)\s*任务摘要[::]/;
|
||||||
|
|
||||||
|
function parseSubAgentDoneLabel(rawContent: any): string | null {
|
||||||
|
const content = (rawContent || '').toString().trim();
|
||||||
|
if (!content) {
|
||||||
|
console.log('[DEBUG_SYSTEM][ui] parseSubAgentDoneLabel: 空内容');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const match = content.match(SUB_AGENT_DONE_PREFIX_RE);
|
||||||
|
const isCompleted = /已完成/.test(content);
|
||||||
|
console.log('[DEBUG_SYSTEM][ui] parseSubAgentDoneLabel', {
|
||||||
|
content,
|
||||||
|
regex: SUB_AGENT_DONE_PREFIX_RE.toString(),
|
||||||
|
matched: !!match,
|
||||||
|
matchAgentId: match?.[1],
|
||||||
|
isCompleted
|
||||||
|
});
|
||||||
|
if (!match || !isCompleted) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const agentId = match[1];
|
||||||
|
return `子智能体${agentId} 任务完成`;
|
||||||
|
}
|
||||||
|
|
||||||
export const uiMethods = {
|
export const uiMethods = {
|
||||||
ensureScrollListener() {
|
ensureScrollListener() {
|
||||||
if (this._scrollListenerReady) {
|
if (this._scrollListenerReady) {
|
||||||
@ -759,10 +783,18 @@ export const uiMethods = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
addSystemMessage(content) {
|
addSystemMessage(content) {
|
||||||
if (this.hideSystemMessages) {
|
console.log('[DEBUG_SYSTEM][ui] addSystemMessage 入参', { content });
|
||||||
|
const subAgentDoneLabel = parseSubAgentDoneLabel(content);
|
||||||
|
if (!subAgentDoneLabel) {
|
||||||
|
// 其他 system 消息全部隐藏,且不进入渲染链路,避免出现空白块
|
||||||
|
console.log('[DEBUG_SYSTEM][ui] addSystemMessage 被拦截(非子智能体完成)', { content });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.chatAddSystemMessage(content);
|
console.log('[DEBUG_SYSTEM][ui] addSystemMessage 通过,写入 action', {
|
||||||
|
original: content,
|
||||||
|
normalizedLabel: subAgentDoneLabel
|
||||||
|
});
|
||||||
|
this.chatAddSystemMessage(subAgentDoneLabel, { variant: 'sub_agent_done' });
|
||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
this.conditionalScrollToBottom();
|
this.conditionalScrollToBottom();
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="messages-area" ref="rootEl">
|
<div class="messages-area" ref="rootEl">
|
||||||
<div class="messages-flow">
|
<div class="messages-flow">
|
||||||
<div v-for="(msg, index) in filteredMessages" :key="index" class="message-block">
|
<div
|
||||||
|
v-for="(msg, index) in filteredMessages"
|
||||||
|
:key="index"
|
||||||
|
class="message-block"
|
||||||
|
:class="{
|
||||||
|
'message-block--sub-agent-notice': isSubAgentNoticeOnlyMessage(msg),
|
||||||
|
'message-block--before-sub-agent-notice': isFollowedBySubAgentNotice(index)
|
||||||
|
}"
|
||||||
|
>
|
||||||
<div v-if="msg.role === 'user'" class="user-message">
|
<div v-if="msg.role === 'user'" class="user-message">
|
||||||
<div class="message-header icon-label">
|
<div class="message-header icon-label">
|
||||||
<span class="icon icon-sm" :style="iconStyleSafe('user')" aria-hidden="true"></span>
|
<span class="icon icon-sm" :style="iconStyleSafe('user')" aria-hidden="true"></span>
|
||||||
@ -24,7 +32,7 @@
|
|||||||
<div v-else-if="msg.role === 'assistant'" class="assistant-message">
|
<div v-else-if="msg.role === 'assistant'" class="assistant-message">
|
||||||
<!-- 在 assistant 消息前显示 AI Assistant 头部 -->
|
<!-- 在 assistant 消息前显示 AI Assistant 头部 -->
|
||||||
<!-- 只有当前一条消息是 user 且当前消息有内容时才显示 -->
|
<!-- 只有当前一条消息是 user 且当前消息有内容时才显示 -->
|
||||||
<div v-if="index > 0 && filteredMessages[index - 1].role === 'user' && (msg.actions?.length > 0 || msg.awaitingFirstContent)" class="message-header icon-label">
|
<div v-if="index > 0 && filteredMessages[index - 1].role === 'user' && (hasRenderableAssistantActions(msg.actions || []) || msg.awaitingFirstContent)" class="message-header icon-label">
|
||||||
<span class="icon icon-sm" :style="iconStyleSafe('bot')" aria-hidden="true"></span>
|
<span class="icon icon-sm" :style="iconStyleSafe('bot')" aria-hidden="true"></span>
|
||||||
<span>{{ aiAssistantName }}</span>
|
<span>{{ aiAssistantName }}</span>
|
||||||
<span v-if="assistantWorkLabel(index)" class="assistant-work-status">{{ assistantWorkLabel(index) }}</span>
|
<span v-if="assistantWorkLabel(index)" class="assistant-work-status">{{ assistantWorkLabel(index) }}</span>
|
||||||
@ -52,6 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<template v-if="blockDisplayMode === 'minimal'">
|
<template v-if="blockDisplayMode === 'minimal'">
|
||||||
<MinimalBlocks
|
<MinimalBlocks
|
||||||
|
v-if="hasRenderableAssistantActions(msg.actions || [])"
|
||||||
:actions="msg.actions || []"
|
:actions="msg.actions || []"
|
||||||
:conversation-running="streamingMessage"
|
:conversation-running="streamingMessage"
|
||||||
:is-latest-message="index === latestMessageIndex"
|
:is-latest-message="index === latestMessageIndex"
|
||||||
@ -87,7 +96,7 @@
|
|||||||
:format-search-domains="formatSearchDomains"
|
:format-search-domains="formatSearchDomains"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-else
|
v-else-if="isActionVisible(group.action)"
|
||||||
class="action-item"
|
class="action-item"
|
||||||
:key="group.action?.id || `${index}-${group.actionIndex}`"
|
:key="group.action?.id || `${index}-${group.actionIndex}`"
|
||||||
:class="{
|
:class="{
|
||||||
@ -139,10 +148,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="group.action?.type === 'system'" class="system-action">
|
<div
|
||||||
<div class="system-action-content">
|
v-else-if="group.action?.type === 'system' && getSubAgentSystemNoticeLabel(group.action)"
|
||||||
{{ group.action.content }}
|
class="sub-agent-system-summary-line"
|
||||||
</div>
|
>
|
||||||
|
{{ getSubAgentSystemNoticeLabel(group.action) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -224,6 +234,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
v-for="(action, actionIndex) in msg.actions || []"
|
v-for="(action, actionIndex) in msg.actions || []"
|
||||||
|
v-if="isActionVisible(action)"
|
||||||
:key="action.id || `${index}-${actionIndex}`"
|
:key="action.id || `${index}-${actionIndex}`"
|
||||||
class="action-item"
|
class="action-item"
|
||||||
:class="{
|
:class="{
|
||||||
@ -274,10 +285,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="action.type === 'system'" class="system-action">
|
<div
|
||||||
<div class="system-action-content">
|
v-else-if="action.type === 'system' && getSubAgentSystemNoticeLabel(action)"
|
||||||
{{ action.content }}
|
class="sub-agent-system-summary-line"
|
||||||
</div>
|
>
|
||||||
|
{{ getSubAgentSystemNoticeLabel(action) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -423,12 +435,25 @@ const userName = computed(() => {
|
|||||||
}
|
}
|
||||||
return personalization.form.user_name || '用户';
|
return personalization.form.user_name || '用户';
|
||||||
});
|
});
|
||||||
const filteredMessages = computed(() =>
|
const filteredMessages = computed(() => {
|
||||||
(props.messages || []).filter(m => !(m && m.metadata && m.metadata.system_injected_image) && m.role !== 'system')
|
const source = props.messages || [];
|
||||||
);
|
const droppedRoleSystem = source.filter(m => m && m.role === 'system');
|
||||||
|
if (droppedRoleSystem.length > 0) {
|
||||||
|
console.log('[DEBUG_SYSTEM][render] filteredMessages 过滤了 role=system 消息', {
|
||||||
|
count: droppedRoleSystem.length,
|
||||||
|
samples: droppedRoleSystem.slice(0, 3)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return source.filter(m => !(m && m.metadata && m.metadata.system_injected_image) && m.role !== 'system');
|
||||||
|
});
|
||||||
const latestMessageIndex = computed(() => filteredMessages.value.length - 1);
|
const latestMessageIndex = computed(() => filteredMessages.value.length - 1);
|
||||||
|
const SUB_AGENT_DONE_LABEL_RE = /^子智能体\d+\s*任务完成$/;
|
||||||
|
const SUB_AGENT_DONE_PREFIX_RE = /^(?:✅\s*)?子智能体\s*#?\s*(\d+)\s*任务摘要[::]/;
|
||||||
|
const RENDERABLE_ACTION_TYPES = new Set(['thinking', 'text', 'tool', 'append', 'append_payload', 'system']);
|
||||||
const nowMs = ref(Date.now());
|
const nowMs = ref(Date.now());
|
||||||
let timerHandle: number | null = null;
|
let timerHandle: number | null = null;
|
||||||
|
const debugLoggedSystemActionKeys = new Set<string>();
|
||||||
|
const debugLoggedUnknownActionKeys = new Set<string>();
|
||||||
|
|
||||||
const DEFAULT_GENERATING_TEXT = '生成中…';
|
const DEFAULT_GENERATING_TEXT = '生成中…';
|
||||||
const rootEl = ref<HTMLElement | null>(null);
|
const rootEl = ref<HTMLElement | null>(null);
|
||||||
@ -486,6 +511,88 @@ function formatDurationMs(durationMs: number): string {
|
|||||||
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSubAgentSystemNoticeLabel(action: any): string | null {
|
||||||
|
if (!action || action.type !== 'system') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const content = typeof action.content === 'string' ? action.content.trim() : '';
|
||||||
|
const key = action?.id || `no-id-${content.slice(0, 32)}`;
|
||||||
|
if (!content) {
|
||||||
|
if (!debugLoggedSystemActionKeys.has(`${key}-empty`)) {
|
||||||
|
console.log('[DEBUG_SYSTEM][render] system action 内容为空', { action });
|
||||||
|
debugLoggedSystemActionKeys.add(`${key}-empty`);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (action.variant === 'sub_agent_done' && SUB_AGENT_DONE_LABEL_RE.test(content)) {
|
||||||
|
if (!debugLoggedSystemActionKeys.has(`${key}-variant-pass`)) {
|
||||||
|
console.log('[DEBUG_SYSTEM][render] 命中 variant 渲染', { action, label: content });
|
||||||
|
debugLoggedSystemActionKeys.add(`${key}-variant-pass`);
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
const m = content.match(SUB_AGENT_DONE_PREFIX_RE);
|
||||||
|
if (m && /已完成/.test(content)) {
|
||||||
|
if (!debugLoggedSystemActionKeys.has(`${key}-regex-pass`)) {
|
||||||
|
console.log('[DEBUG_SYSTEM][render] 命中 regex 渲染', { action, normalized: `子智能体${m[1]} 任务完成` });
|
||||||
|
debugLoggedSystemActionKeys.add(`${key}-regex-pass`);
|
||||||
|
}
|
||||||
|
return `子智能体${m[1]} 任务完成`;
|
||||||
|
}
|
||||||
|
if (!debugLoggedSystemActionKeys.has(`${key}-blocked`)) {
|
||||||
|
console.log('[DEBUG_SYSTEM][render] system action 被渲染层拦截', {
|
||||||
|
action,
|
||||||
|
regex: SUB_AGENT_DONE_PREFIX_RE.toString(),
|
||||||
|
completed: /已完成/.test(content)
|
||||||
|
});
|
||||||
|
debugLoggedSystemActionKeys.add(`${key}-blocked`);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionVisible(action: any): boolean {
|
||||||
|
if (!action) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const actionType = action.type;
|
||||||
|
if (!RENDERABLE_ACTION_TYPES.has(actionType)) {
|
||||||
|
const key = action?.id || `unknown-${actionType || 'none'}`;
|
||||||
|
if (!debugLoggedUnknownActionKeys.has(key)) {
|
||||||
|
console.log('[DEBUG_SYSTEM][render] 未知 action.type,已跳过渲染', {
|
||||||
|
actionType,
|
||||||
|
action
|
||||||
|
});
|
||||||
|
debugLoggedUnknownActionKeys.add(key);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (action.type !== 'system') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !!getSubAgentSystemNoticeLabel(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasRenderableAssistantActions(actions: any[] = []): boolean {
|
||||||
|
return (actions || []).some((action) => isActionVisible(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSubAgentNoticeOnlyMessage(msg: any): boolean {
|
||||||
|
if (!msg || msg.role !== 'assistant') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const visibleActions = (msg.actions || []).filter((action: any) => isActionVisible(action));
|
||||||
|
if (visibleActions.length !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const onlyAction = visibleActions[0];
|
||||||
|
return onlyAction?.type === 'system' && !!getSubAgentSystemNoticeLabel(onlyAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFollowedBySubAgentNotice(index: number): boolean {
|
||||||
|
const next = filteredMessages.value[index + 1];
|
||||||
|
return !!next && isSubAgentNoticeOnlyMessage(next);
|
||||||
|
}
|
||||||
|
|
||||||
function assistantWorkLabel(index: number): string {
|
function assistantWorkLabel(index: number): string {
|
||||||
if (index <= 0) {
|
if (index <= 0) {
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@ -85,6 +85,19 @@
|
|||||||
<div v-else v-html="renderMarkdown(group.content || '', false)"></div>
|
<div v-else v-html="renderMarkdown(group.content || '', false)"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="group.type === 'system'" class="summary-group sub-agent-system-group">
|
||||||
|
<div class="summary-line-text sub-agent-system-summary-line">
|
||||||
|
<div class="summary-content-wrapper">
|
||||||
|
<span class="summary-preview">{{ group.content || '' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-status-icon">
|
||||||
|
<svg class="check-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<circle cx="12" cy="12" r="10" />
|
||||||
|
<polyline points="7.5 12 10.5 15 16.5 9" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -118,7 +131,7 @@ interface Step {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface BlockGroup {
|
interface BlockGroup {
|
||||||
type: 'summary' | 'text';
|
type: 'summary' | 'text' | 'system';
|
||||||
id: string;
|
id: string;
|
||||||
actions?: Action[];
|
actions?: Action[];
|
||||||
content?: string;
|
content?: string;
|
||||||
@ -204,7 +217,7 @@ const blockGroups = computed(() => {
|
|||||||
props.actions.forEach((action, idx) => {
|
props.actions.forEach((action, idx) => {
|
||||||
if (action.type === 'thinking' || action.type === 'tool') {
|
if (action.type === 'thinking' || action.type === 'tool') {
|
||||||
currentGroup.push(action);
|
currentGroup.push(action);
|
||||||
} else if (action.type === 'text') {
|
} else if (action.type === 'text' || action.type === 'system') {
|
||||||
// 先保存当前的 thinking/tool 组
|
// 先保存当前的 thinking/tool 组
|
||||||
if (currentGroup.length > 0) {
|
if (currentGroup.length > 0) {
|
||||||
// 使用第一个 action 的 id 作为 group id,保证稳定性
|
// 使用第一个 action 的 id 作为 group id,保证稳定性
|
||||||
@ -217,13 +230,26 @@ const blockGroups = computed(() => {
|
|||||||
groupIndex++;
|
groupIndex++;
|
||||||
currentGroup = [];
|
currentGroup = [];
|
||||||
}
|
}
|
||||||
// 添加 text 组
|
if (action.type === 'text') {
|
||||||
groups.push({
|
const text = typeof action.content === 'string' ? action.content : '';
|
||||||
type: 'text',
|
if (!text.trim()) {
|
||||||
id: `text-${idx}`,
|
return;
|
||||||
content: action.content,
|
}
|
||||||
streaming: action.streaming
|
// 添加 text 组
|
||||||
});
|
groups.push({
|
||||||
|
type: 'text',
|
||||||
|
id: `text-${idx}`,
|
||||||
|
content: text,
|
||||||
|
streaming: action.streaming
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 添加 system 组(用于子智能体完成通知,保持顺序)
|
||||||
|
groups.push({
|
||||||
|
type: 'system',
|
||||||
|
id: `system-${idx}`,
|
||||||
|
content: action.content
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -494,6 +520,18 @@ watch(() => props.actions, () => {
|
|||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sub-agent-system-group {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-agent-system-group .sub-agent-system-summary-line {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-agent-system-group .sub-agent-system-summary-line:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
/* 摘要行(只有文字) */
|
/* 摘要行(只有文字) */
|
||||||
.summary-line-text {
|
.summary-line-text {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|||||||
@ -289,15 +289,25 @@ export const useChatStore = defineStore('chat', {
|
|||||||
msg.streamingText = '';
|
msg.streamingText = '';
|
||||||
msg.currentStreamingType = null;
|
msg.currentStreamingType = null;
|
||||||
},
|
},
|
||||||
addSystemMessage(content: string) {
|
addSystemMessage(content: string, meta: any = null) {
|
||||||
const msg = this.ensureAssistantMessage();
|
const msg = this.ensureAssistantMessage();
|
||||||
clearAwaitingFirstContent(msg);
|
clearAwaitingFirstContent(msg);
|
||||||
|
console.log('[DEBUG_SYSTEM][store] addSystemMessage 写入 actions', {
|
||||||
|
content,
|
||||||
|
meta,
|
||||||
|
currentMessageIndex: this.currentMessageIndex,
|
||||||
|
actionsBefore: Array.isArray(msg?.actions) ? msg.actions.length : -1
|
||||||
|
});
|
||||||
msg.actions.push({
|
msg.actions.push({
|
||||||
id: randomId('system'),
|
id: randomId('system'),
|
||||||
type: 'system',
|
type: 'system',
|
||||||
content,
|
content,
|
||||||
|
variant: meta?.variant || null,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
});
|
});
|
||||||
|
console.log('[DEBUG_SYSTEM][store] addSystemMessage 写入完成', {
|
||||||
|
actionsAfter: Array.isArray(msg?.actions) ? msg.actions.length : -1
|
||||||
|
});
|
||||||
},
|
},
|
||||||
getActiveThinkingAction(msg: any) {
|
getActiveThinkingAction(msg: any) {
|
||||||
if (!msg || !Array.isArray(msg.actions)) {
|
if (!msg || !Array.isArray(msg.actions)) {
|
||||||
|
|||||||
@ -363,6 +363,26 @@
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-block.message-block--sub-agent-notice {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-block.message-block--before-sub-agent-notice {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-block.message-block--before-sub-agent-notice .minimal-blocks-container {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-block.message-block--before-sub-agent-notice .minimal-blocks-container > :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-block.message-block--sub-agent-notice .minimal-blocks-container {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.user-message {
|
.user-message {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -937,6 +957,14 @@ body[data-theme='dark'] .more-icon {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sub-agent-system-summary-line {
|
||||||
|
padding: 0 20px 0 15px;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--claude-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.append-block,
|
.append-block,
|
||||||
.append-placeholder {
|
.append-placeholder {
|
||||||
margin: 12px 0;
|
margin: 12px 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user