feat(h5): show rotating loading tips during agent-run execution

Surface backend loading_tip SSE events in chat UI with shared tip pool
and styles for long-running TKMind 智趣 tasks.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-27 09:33:50 +08:00
parent 8f91c52c67
commit 8bdb6e2442
9 changed files with 191 additions and 9 deletions
+2
View File
@@ -198,6 +198,7 @@ export function ChatView({
error,
notice,
pendingTool,
taskLoadingTip,
submit,
stop,
approveTool,
@@ -577,6 +578,7 @@ export function ChatView({
onBalanceUpdate={(nextBalance) => completeRecharge(nextBalance)}
onGrantedSkillsUpdate={onGrantedSkillsUpdate}
onOpenRecharge={() => openRecharge(false)}
taskLoadingTip={taskLoadingTip}
onSubmit={(text, imageUrls, previewImageUrls, options) =>
void submit(
text,
+9 -3
View File
@@ -145,7 +145,7 @@ function isToolOnlyAssistantMessage(message: Message) {
);
}
function TypingBubble() {
function TypingBubble({ tip }: { tip?: string | null }) {
return (
<div className="msg-bubble msg-bubble-assistant msg-typing">
<span className="typing-dots">
@@ -153,6 +153,7 @@ function TypingBubble() {
<span />
<span />
</span>
{tip ? <p className="msg-typing-tip">{tip}</p> : null}
</div>
);
}
@@ -324,6 +325,7 @@ function MessageRow({
compact = false,
activeToolMessage = false,
showInlineTyping = false,
typingTip = null,
memoryRecallByMessageId = {},
messageIndex = 0,
}: {
@@ -341,6 +343,7 @@ function MessageRow({
compact?: boolean;
activeToolMessage?: boolean;
showInlineTyping?: boolean;
typingTip?: string | null;
memoryRecallByMessageId?: Record<string, { count: number; previews: string[] }>;
messageIndex?: number;
}) {
@@ -362,7 +365,7 @@ function MessageRow({
<TKMindAvatar />
<div className="msg-content">
{showInlineTyping ? (
<TypingBubble />
<TypingBubble tip={typingTip} />
) : (
<>
<ToolBadge message={message} active={activeToolMessage} />
@@ -537,6 +540,7 @@ export function MessageList({
publishUsername,
compact = false,
memoryRecallByMessageId = {},
typingTip = null,
}: {
messages: Message[];
streaming: boolean;
@@ -549,6 +553,7 @@ export function MessageList({
publishUsername?: string;
compact?: boolean;
memoryRecallByMessageId?: Record<string, { count: number; previews: string[] }>;
typingTip?: string | null;
}) {
const { avatarUrl } = useUserAvatar();
const renderableMessages = messages.filter(shouldShowChatMessage);
@@ -605,6 +610,7 @@ export function MessageList({
compact={compact}
activeToolMessage={message === activeToolMessage}
showInlineTyping={showEndTyping && message === inlineTypingMessage}
typingTip={showEndTyping && message === inlineTypingMessage ? typingTip : null}
memoryRecallByMessageId={memoryRecallByMessageId}
messageIndex={index}
/>
@@ -615,7 +621,7 @@ export function MessageList({
<div className="msg-row msg-row-assistant" role="status" aria-live="polite" aria-label="助手正在回复">
<TKMindAvatar />
<div className="msg-content">
<TypingBubble />
<TypingBubble tip={typingTip} />
</div>
</div>
)}
+2 -1
View File
@@ -58,7 +58,7 @@ export function SpaceChatPanel({
uploadChatAttachment,
retryConnect,
} = chat;
const { capabilities, grantedSkills, followAgentRun, goalRunEnabled, balanceCents } = mainChat;
const { capabilities, grantedSkills, followAgentRun, goalRunEnabled, balanceCents, taskLoadingTip } = mainChat;
const [localGrantedSkills, setLocalGrantedSkills] = useState<string[] | undefined>();
const effectiveGrantedSkills = localGrantedSkills ?? grantedSkills;
@@ -180,6 +180,7 @@ export function SpaceChatPanel({
onBalanceUpdate={(nextBalance) => completeRecharge(nextBalance)}
onGrantedSkillsUpdate={handleGrantedSkillsUpdate}
onOpenRecharge={() => openRecharge(false)}
taskLoadingTip={taskLoadingTip}
onSubmit={(text, imageUrls, previewImageUrls, options) =>
chatBridge
? void submit(