继续保留润色命令底层错误

不再把 Tauri 润色异常吞成空回包

补充共享润色链路回归测试和文档
This commit is contained in:
kdletters
2026-10-05 21:49:31 +08:00
parent c95d9849ee
commit e1b17c6f1b
4 changed files with 20 additions and 15 deletions
@@ -84,7 +84,8 @@ export function shouldRemindChatPromptPolish({
* 走平台 LLM 路由的短文本润色。
* 复用 `polish_local_project_prompt` 这条短文本生成通道:计费在平台 LLM 路由侧完成,
* 这里不自建计费、不落盘。
* 失败 / 超时 / 未配置模型统一返回 `null`,调用方保留原文并给出可重试提示。
* 空回包 / 未配置模型返回 `null`;Tauri 调用抛出的平台、网络、IPC 正文继续上抛,
* 由共享 `usePromptPolish` 统一脱敏后展示。
*/
export async function requestChatPromptPolish(
prompt: string,
@@ -96,14 +97,10 @@ export async function requestChatPromptPolish(
return null;
}
const trimmedContext = context?.trim();
try {
const result = await invoke<string>('polish_local_project_prompt', {
prompt: trimmed,
context: trimmedContext ? trimmedContext : null,
});
const polished = typeof result === 'string' ? result.trim() : '';
return polished ? polished : null;
} catch {
return null;
}
const result = await invoke<string>('polish_local_project_prompt', {
prompt: trimmed,
context: trimmedContext ? trimmedContext : null,
});
const polished = typeof result === 'string' ? result.trim() : '';
return polished ? polished : null;
}
@@ -280,7 +280,7 @@ describe('requestChatPromptPolish', () => {
});
});
test('omits blank context and keeps failures recoverable', async () => {
test('omits blank context and preserves native failure details', async () => {
const invoke = installPolishingInvoke('润色结果');
await requestChatPromptPolish('原始需求', ' ');
expect(invoke).toHaveBeenCalledWith('polish_local_project_prompt', {
@@ -292,7 +292,9 @@ describe('requestChatPromptPolish', () => {
throw new Error('platform llm unavailable');
});
installTauriInvoke(failing);
await expect(requestChatPromptPolish('原始需求')).resolves.toBeNull();
await expect(requestChatPromptPolish('原始需求')).rejects.toThrow(
'platform llm unavailable',
);
await expect(requestChatPromptPolish(' ')).resolves.toBeNull();
});
@@ -344,7 +346,9 @@ describe('聊天输入区 AI 润色与发送前提醒', () => {
await user.click(screen.getByRole('button', { name: 'AI 润色' }));
expect(await composerText()).toBe('原本的需求');
expect(await screen.findByText('AI 润色失败,可重试')).not.toBeNull();
expect(
await screen.findByText('AI 润色失败,可重试:platform llm timeout'),
).not.toBeNull();
expect(screen.queryByRole('button', { name: '恢复原文' })).toBeNull();
});
@@ -425,7 +429,9 @@ describe('聊天输入区 AI 润色与发送前提醒', () => {
);
expect(
await screen.findByText('AI 润色失败,可重试或使用原文提交'),
await screen.findByText(
'AI 润色失败,可重试或使用原文提交:platform llm timeout',
),
).not.toBeNull();
expect(onSubmitDraft).not.toHaveBeenCalled();
expect(await composerText()).toBe(LONG_PROMPT);
@@ -140,6 +140,7 @@ DirectProject 已经解决过同一类问题([`【ADR】DirectProject命令接
- 错误报告通知自身的快照读取失败也不能被通知组件的重试逻辑吞掉;重试耗尽后必须显示安全正文和再次读取入口。
- 共享异步操作 hook(包括 Prompt Polish)捕获异常时,操作指引可以保留,但固定失败文案后必须附精确脱敏正文。
- 资源画布历史任务账本读取属于用户可见的恢复路径:异常正文必须进入提示条;只有响应形状错误这类没有底层异常的情况才使用明确的契约提示。
- 异步业务 facade 不得把底层异常折成“空结果”来逃避错误处理;只有真实的空回包、未配置或浏览器桥不可用等无正文事实允许返回空值,Tauri/网络/IPC 异常必须上抛到统一脱敏出口。
## 后果与边界
@@ -61,3 +61,4 @@ DirectProject 回合失败在确认不是客户端内部不可归类故障时,
- 错误报告通知读取本地待报告快照失败原来只重试后静默消失;现显示“项目诊断读取失败”及安全正文,并提供重试入口。
- 共享 Prompt Polish hook 的注入请求/规范化/回填异常原来只显示固定失败提示;现保留精确脱敏后的异常正文,聊天输入和资源润色共用同一口径。
- 资源画布历史生成任务账本读取失败原来统一显示“暂时无法恢复历史任务”;现在保留 Tauri/文件读取正文,非数组响应仍单独保留契约错误提示。
- 发现默认 `requestChatPromptPolish` 还会把 Tauri 润色命令异常吞成 `null`,导致共享 hook 无法看到平台正文;现仅对空回包/桥不可用保留 `null`,原生异常继续上抛并统一脱敏。