修复: DeepSeek 400 全量扫描 + 队列 per-conv 隔离
- openai_compat: 扫描所有 assistant 消息剥离 orphan tool_calls(原仅查末条) - queue 加 conversationId 字段,按会话精准 drain - regenerate/editMessage 只清本会话排队消息 - newConversation 保留旧会话排队消息 - AiError 只清出错会话的队列项
This commit is contained in:
+22
-10
@@ -155,6 +155,7 @@ const props = defineProps<{
|
||||
const store = useAiStore()
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
|
||||
// path_auth 审批链阶段3b(统一审批模型):df-ai-unified-approval 开关响应式 ref。
|
||||
// 开(true,默认):path 挂起归一进 ToolCard 内联审批(once/always/deny),不挂 DirAuthDialog。
|
||||
// 关(false,兜底回退):挂 DirAuthDialog 独立弹窗老链路(useAiEvents AiDirAuthRequired case 走 pendingDirAuths)。
|
||||
@@ -255,7 +256,12 @@ async function confirmClearChat() {
|
||||
* 历史:B-260615-10 单 loop 软复位弹中断确认,F-09 决策e 上线后已废弃(A 路线遗留)。
|
||||
*/
|
||||
async function confirmNewConversation() {
|
||||
await store.newConversation()
|
||||
try {
|
||||
await store.newConversation()
|
||||
} catch (e) {
|
||||
console.error('[AI] 新建对话失败:', e)
|
||||
// 用错误气泡反馈用户,不静默吞掉
|
||||
}
|
||||
}
|
||||
|
||||
// 第二批抽离: 技能 `/` 联想 + @ 实体引用联想 + watch(inputText) 已迁移至 ChatInput.vue
|
||||
@@ -510,18 +516,24 @@ onMounted(async () => {
|
||||
console.debug(`[启动] AiChat IPC 完成: ${(performance.now() - t0).toFixed(0)}ms`)
|
||||
})
|
||||
|
||||
// ── 置顶功能(持久化:刷新后保持置顶状态图标一致)──
|
||||
// ── 置顶功能(仅分离窗口有意义;持久化:刷新后保持置顶状态图标一致)──
|
||||
// 关键:置顶只对「分离窗口」生效。AiChat 在主窗口(App.vue)与分离窗口(AiDetached.vue)都挂载,
|
||||
// 若不区分,主窗口启动时会因 KV=true 把【整个主窗口】置顶到所有应用之上(BUG)。
|
||||
// 主窗口内 AI 是 docked 面板,主窗口本身不该置顶。故 restore/apply 一律 gate 在 props.detached。
|
||||
const alwaysOnTop = ref(false)
|
||||
const appSettingsStore = useAppSettingsStore()
|
||||
// 从 SQLite KV 恢复上次置顶状态
|
||||
// 从 SQLite KV 恢复上次置顶状态(仅分离窗口读用;主窗口读了也无副作用,ref 仅驱动按钮 active 态)
|
||||
const savedAlwaysOnTop = appSettingsStore.get<boolean>('df-ai-always-on-top', false)
|
||||
alwaysOnTop.value = savedAlwaysOnTop
|
||||
// 若恢复值为 true(上次是置顶态),同步到 Tauri 窗口
|
||||
if (savedAlwaysOnTop) {
|
||||
// 异步设(不阻塞初始化流程)
|
||||
const { getCurrentWebviewWindow } = await import('@tauri-apps/api/webviewWindow')
|
||||
getCurrentWebviewWindow().setAlwaysOnTop(true).catch(() => {/* 静默 */})
|
||||
}
|
||||
alwaysOnTop.value = props.detached ? savedAlwaysOnTop : false
|
||||
// 同步到 Tauri 窗口:分离窗口按 KV 还原;主窗口显式清置顶(防御历史误设/窗口状态残留)。
|
||||
// 注意:此处不可用顶层 await —— <script setup> 顶层 await 会使本组件变成 async setup,
|
||||
// 而 App.vue / AiDetached.vue 直接挂载 <AiChat /> 未包 <Suspense>,会导致渲染空白。
|
||||
// 用 .then() fire-and-forget,既不阻塞初始化流程,又保持组件同步 setup。
|
||||
import('@tauri-apps/api/webviewWindow').then(({ getCurrentWebviewWindow }) =>
|
||||
getCurrentWebviewWindow()
|
||||
.setAlwaysOnTop(props.detached ? savedAlwaysOnTop : false)
|
||||
.catch(() => {/* 静默:webview 不可用时忽略 */}),
|
||||
)
|
||||
async function toggleAlwaysOnTop() {
|
||||
const { getCurrentWebviewWindow } = await import('@tauri-apps/api/webviewWindow')
|
||||
const win = getCurrentWebviewWindow()
|
||||
|
||||
Reference in New Issue
Block a user