fix(ui): harden product-facing interaction flows
This commit is contained in:
@@ -25,6 +25,13 @@ test('deriveUserFacingText removes routing hint and skill preface from agent pay
|
||||
assert.equal(deriveUserFacingText(agentPayload), userText);
|
||||
});
|
||||
|
||||
test('deriveUserFacingText removes page-data prompt persisted as display text', () => {
|
||||
const userText = '帮我做一个日记页面,可以每天写日记,其他人可以评价';
|
||||
const persistedDisplayText = `${buildAutoChatSkillPrefix(userText, ['page-data-collect'])}${userText}`;
|
||||
assert.match(persistedDisplayText, /page-data-collect/);
|
||||
assert.equal(deriveUserFacingText(persistedDisplayText), userText);
|
||||
});
|
||||
|
||||
test('deriveUserFacingText removes Memind task orchestration prefix', () => {
|
||||
const userText = '帮我生成深度搜索报告';
|
||||
const agentPayload = [
|
||||
|
||||
@@ -36,6 +36,11 @@ const messageTs = read('src/utils/message.ts');
|
||||
assertIncludes(messageTs, 'deriveUserFacingText', 'message.ts');
|
||||
assertIncludes(messageTs, 'deriveAssistantFacingText', 'message.ts');
|
||||
assertIncludes(messageTs, 'chat-finish-sync.mjs', 'message.ts');
|
||||
assertIncludes(
|
||||
messageTs,
|
||||
'deriveUserFacingText(message.metadata.displayText)',
|
||||
'message.ts metadata displayText guard',
|
||||
);
|
||||
|
||||
const conversationDisplay = read('conversation-display.mjs');
|
||||
assertIncludes(conversationDisplay, 'TASK_ROUTING_HINT_RE', 'conversation-display.mjs');
|
||||
|
||||
@@ -1586,7 +1586,7 @@ export function MindSpacePageDetail({
|
||||
<button
|
||||
type="button"
|
||||
className={previewRefreshPending ? 'is-refresh-pending' : undefined}
|
||||
onClick={handleManualPreviewRefresh}
|
||||
onClick={() => handleManualPreviewRefresh()}
|
||||
title={previewRefreshPending ? '草稿已有新内容,点击刷新预览' : '将当前草稿同步到预览'}
|
||||
>
|
||||
刷新预览{previewRefreshPending ? ' · 有新修改' : ''}
|
||||
@@ -1684,15 +1684,21 @@ export function MindSpacePageDetail({
|
||||
) : null}
|
||||
|
||||
{confirmPublicationStatusOpen && page?.publication ? (
|
||||
<MindSpaceModal className="mindspace-confirm-publication-status-modal">
|
||||
<MindSpaceModal
|
||||
open={confirmPublicationStatusOpen}
|
||||
onClose={() => setConfirmPublicationStatusOpen(false)}
|
||||
title="页面预览期确认"
|
||||
eyebrow="PUBLICATION STATUS"
|
||||
className="mindspace-confirm-publication-status-modal"
|
||||
disableClose={statusConfirming}
|
||||
>
|
||||
<div className="mindspace-modal-content">
|
||||
<h3>页面预览期确认</h3>
|
||||
<p>你的页面当前处于 30 分钟预览期。请选择后续状态:</p>
|
||||
<div className="mindspace-modal-actions">
|
||||
<button
|
||||
className="mindspace-secondary"
|
||||
disabled={statusConfirming}
|
||||
onClick={() => confirmPublicationStatus('private')}
|
||||
onClick={() => confirmPublicationStatus('owner_only')}
|
||||
>
|
||||
{statusConfirming ? '处理中...' : '改为私有'}
|
||||
</button>
|
||||
|
||||
@@ -477,6 +477,10 @@ function formatBytes(bytes: number) {
|
||||
|
||||
type AssetFilter = 'all' | 'images' | 'files' | 'pages';
|
||||
|
||||
function previewBlocked() {
|
||||
return new Error('预览模式仅供查看,不能修改内容');
|
||||
}
|
||||
|
||||
function canGenerateWithAgent(asset: MindSpaceAsset) {
|
||||
const textLikeMimeTypes = new Set([
|
||||
'text/plain',
|
||||
|
||||
@@ -17,7 +17,16 @@ export function VoiceInputDialog({
|
||||
onSend: (text: string) => void;
|
||||
onError?: (message: string) => void;
|
||||
}) {
|
||||
const { phase, text, analyser, liveRecognition, stopListening, finishFallbackRecording, resetSession } =
|
||||
const {
|
||||
phase,
|
||||
text,
|
||||
analyser,
|
||||
liveRecognition,
|
||||
updateText,
|
||||
stopListening,
|
||||
finishFallbackRecording,
|
||||
resetSession,
|
||||
} =
|
||||
useVoiceSession({
|
||||
active: open && !disabled,
|
||||
onError,
|
||||
|
||||
@@ -204,7 +204,7 @@ export function getDisplayText(message: Message): string {
|
||||
// REGRESSION GUARD: never show agent-only routing/skill prefixes in the chat UI.
|
||||
if (message.role === 'user') {
|
||||
if ('displayText' in message.metadata && message.metadata.displayText != null) {
|
||||
return stripImageUrlLines(message.metadata.displayText);
|
||||
return stripImageUrlLines(deriveUserFacingText(message.metadata.displayText));
|
||||
}
|
||||
const raw = message.content
|
||||
.filter((c): c is Extract<MessageContent, { type: 'text' }> => c.type === 'text')
|
||||
|
||||
Reference in New Issue
Block a user