fix(chat): 澄清问题卡片 UX 优化 — 去悬空引用 + 默认展开
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
- 提示词增加 ask_clarification 引用规则,避免 LLM 在文本中生成 "以下信息"/"比如:"等悬空引用短语 - 新增 stripDanglingClarificationRef 前端安全网,当消息包含 ask_clarification 工具调用时自动移除末尾悬空引用 - 澄清卡片默认展开,让用户直接看到选项无需额外点击
This commit is contained in:
@@ -426,6 +426,7 @@ impl Kernel {
|
|||||||
prompt.push_str("- Provide clear options when possible\n");
|
prompt.push_str("- Provide clear options when possible\n");
|
||||||
prompt.push_str("- Include brief context about why you're asking\n");
|
prompt.push_str("- Include brief context about why you're asking\n");
|
||||||
prompt.push_str("- After receiving clarification, proceed immediately\n");
|
prompt.push_str("- After receiving clarification, proceed immediately\n");
|
||||||
|
prompt.push_str("- CRITICAL: When calling ask_clarification, do NOT repeat the options in your text response. The options will be shown in a dedicated card above your reply. Simply greet the user and briefly explain why you need clarification — avoid phrases like \"以下信息\" or \"the following options\" that imply a list follows in your text\n");
|
||||||
|
|
||||||
prompt
|
prompt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -665,6 +665,28 @@ function stripToolNarration(content: string): string {
|
|||||||
return result || content;
|
return result || content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strip dangling clarification references from text when ask_clarification tool was called.
|
||||||
|
* When the LLM calls ask_clarification, it often ends its text with phrases like
|
||||||
|
* "比如:" / "以下信息" / "以下选项" that reference the tool output — but the tool output
|
||||||
|
* is rendered in a separate ClarificationCard, so these become confusing dead-end sentences.
|
||||||
|
*/
|
||||||
|
function stripDanglingClarificationRef(text: string, hasClarificationTool: boolean): string {
|
||||||
|
if (!hasClarificationTool || !text) return text;
|
||||||
|
// Match trailing dangling references in Chinese and English
|
||||||
|
const patterns = [
|
||||||
|
/[,,]\s*可以(?:提供以下|告诉我更多细节,)?(?:信息|选项|方向|细节|分类|类型)[::]\s*$/,
|
||||||
|
/[,,]\s*比如[::]\s*$/,
|
||||||
|
/[,,]\s*(?:例如|譬如|如以下)[::]\s*$/,
|
||||||
|
/,\s*(?:for example|such as|like|the following)[::]?\s*$/i,
|
||||||
|
];
|
||||||
|
for (const pat of patterns) {
|
||||||
|
const stripped = text.replace(pat, '');
|
||||||
|
if (stripped !== text) return stripped;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
function MessageBubble({ message, onRetry }: { message: Message; setInput?: (text: string) => void; onRetry?: () => void }) {
|
function MessageBubble({ message, onRetry }: { message: Message; setInput?: (text: string) => void; onRetry?: () => void }) {
|
||||||
if (message.role === 'tool') {
|
if (message.role === 'tool') {
|
||||||
return null;
|
return null;
|
||||||
@@ -749,7 +771,10 @@ function MessageBubble({ message, onRetry }: { message: Message; setInput?: (tex
|
|||||||
? (isUser
|
? (isUser
|
||||||
? message.content
|
? message.content
|
||||||
: <StreamingText
|
: <StreamingText
|
||||||
content={stripToolNarration(message.content)}
|
content={stripDanglingClarificationRef(
|
||||||
|
stripToolNarration(message.content),
|
||||||
|
toolCallSteps?.some(s => s.toolName === 'ask_clarification') ?? false,
|
||||||
|
)}
|
||||||
isStreaming={!!message.streaming}
|
isStreaming={!!message.streaming}
|
||||||
className="text-gray-700 dark:text-gray-200"
|
className="text-gray-700 dark:text-gray-200"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -166,7 +166,8 @@ interface ToolStepRowProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ToolStepRow({ step, isActive, showConnector }: ToolStepRowProps) {
|
function ToolStepRow({ step, isActive, showConnector }: ToolStepRowProps) {
|
||||||
const [expanded, setExpanded] = useState(false);
|
// Clarification cards default to expanded so users see options immediately
|
||||||
|
const [expanded, setExpanded] = useState(step.toolName === 'ask_clarification');
|
||||||
const Icon = getToolIcon(step.toolName);
|
const Icon = getToolIcon(step.toolName);
|
||||||
const label = getToolLabel(step.toolName);
|
const label = getToolLabel(step.toolName);
|
||||||
const isRunning = step.status === 'running';
|
const isRunning = step.status === 'running';
|
||||||
|
|||||||
Reference in New Issue
Block a user