优化: 代码质量收尾(搜索索引补全+编译警告清理+i18n核验+String替newtype)

This commit is contained in:
2026-07-01 12:11:35 +08:00
parent 0338210ba2
commit 6771d396f0
15 changed files with 242 additions and 36 deletions

View File

@@ -14,7 +14,7 @@ import { reactive } from 'vue'
import { aiApi } from '@/api'
import { useAppSettingsStore } from '@/stores/appSettings'
import { t } from '@/i18n/i18n-helpers'
import type { AiMessage, AiToolCallInfo, ConvState } from '@/api/types'
import type { AiMessage, AiToolCallInfo, ConvState, MessageId } from '@/api/types'
/**
@@ -154,7 +154,7 @@ export function startApprovalTimer(
console.error('[AI] 审批超时自动拒绝 IPC 未送达:', e)
})
getMessages().push({
id: `approval-timeout-${nextMsgId()}`,
id: `approval-timeout-${nextMsgId()}` as MessageId,
role: 'assistant',
content: t('ai.approvalTimeout', { toolName }),
isError: true,

View File

@@ -12,7 +12,7 @@ import { persistUiState } from './useAiPanel'
import { setStreaming } from './streamingGuard'
import { nextMsgId, getConvState, clearConvStreamState, startApprovalTimer } from './aiShared'
import { t } from '@/i18n/i18n-helpers'
import type { AiConversationDetail, AiMessage, AiToolCallInfo } from '@/api/types'
import type { AiConversationDetail, AiMessage, AiToolCallInfo, ConvId } from '@/api/types'
const appSettings = useAppSettingsStore()
@@ -28,7 +28,7 @@ async function loadConversations() {
&& !state.conversations.some(c => c.id === state.activeConversationId)) {
const now = String(Date.now())
state.conversations.unshift({
id: state.activeConversationId,
id: state.activeConversationId as ConvId,
title: null,
provider_id: null,
model: null,
@@ -102,7 +102,7 @@ export async function switchConversation(id: string) {
if (mySwitchId !== _latestSwitchId) return
void appSettings.set('df-ai-active-conv', created.id)
// 用新对话 id 重走后续逻辑
detail = { id: created.id, title: null, messages: '[]' }
detail = { id: created.id as ConvId, title: null, messages: '[]' }
state.messages = []
notifyConversationChanged()
void loadConversations()

View File

@@ -32,7 +32,7 @@ export { getConvState } from './aiShared'
import { resetStreamWatchdog, clearStreamWatchdog, clearAllStreamWatchdogs } from './useAiStream'
import { setStreaming } from './streamingGuard'
import { loadConversations } from './useAiConversations'
import type { AiChatEvent, AiMessage, AiToolCallInfo } from '@/api/types'
import type { AiChatEvent, AiMessage, AiToolCallInfo, MessageId } from '@/api/types'
let _unlistenAiEvent: (() => void) | null = null
let _unlistenConvChanged: (() => void) | null = null
@@ -283,7 +283,7 @@ function handleStreamingEvent(event: AiChatEvent): boolean {
flushCurrentText()
state.currentText = ''
state.messages.push({
id: `ai-${nextMsgId()}`,
id: `ai-${nextMsgId()}` as MessageId,
role: 'assistant',
content: '',
timestamp: Date.now(),
@@ -313,7 +313,7 @@ function handleStreamingEvent(event: AiChatEvent): boolean {
lastMsg.content = retryText
} else {
state.messages.push({
id: `err-${nextMsgId()}`,
id: `err-${nextMsgId()}` as MessageId,
role: 'assistant',
content: retryText,
isError: true,
@@ -557,7 +557,7 @@ function handleUserMessageEvent(event: AiChatEvent): boolean {
return true
}
state.messages.push({
id: `user-${nextMsgId()}`,
id: `user-${nextMsgId()}` as MessageId,
role: 'user',
content: event.message,
timestamp: Date.now(),
@@ -623,7 +623,7 @@ function handleLifecycleEvent(event: AiChatEvent): boolean {
// 注:此系统提示仅前端展示,后端已独立 push 到 session.messages 落库。
if (event.incomplete) {
state.messages.push({
id: `incomplete-${nextMsgId()}`,
id: `incomplete-${nextMsgId()}` as MessageId,
role: 'assistant',
content: t('ai.responseIncomplete'),
timestamp: Date.now(),
@@ -667,7 +667,7 @@ function handleLifecycleEvent(event: AiChatEvent): boolean {
// AiMessage 类型未含 errorType 字段(不在本批白名单),用对象字面量 + cast 扩展;
// 消费方(AiChat.vue canOpenSettings)经同 cast 读取,类型闭环在两端,不污染 types.ts。
state.messages.push({
id: `err-${nextMsgId()}`,
id: `err-${nextMsgId()}` as MessageId,
role: 'assistant',
content: friendlyError(event.error),
isError: true,

View File

@@ -19,7 +19,7 @@ import { invoke } from '@tauri-apps/api/core'
import { ref } from 'vue'
import { aiApi } from '@/api'
import { state } from '@/stores/ai'
import type { ContentPart, AiMessage, MentionSpan } from '@/api/types'
import type { ContentPart, AiMessage, MentionSpan, MessageId } from '@/api/types'
import { t } from '@/i18n/i18n-helpers'
import { resetStreamWatchdog, clearStreamWatchdog } from './useAiStream'
import { setStreaming } from './streamingGuard'
@@ -73,7 +73,7 @@ const modelOverride = ref<string | null>(null)
async function doSend(text: string, skill?: string, force = false, parts?: ContentPart[], spans?: MentionSpan[]) {
const userMsgId = `user-${nextMsgId()}`
state.messages.push({
id: userMsgId,
id: userMsgId as MessageId,
role: 'user',
content: text.trim(),
// 仅在非空时挂 parts(纯文本消息保持 undefined,渲染走原 content 路径零回归)
@@ -85,7 +85,7 @@ async function doSend(text: string, skill?: string, force = false, parts?: Conte
const aiMsgId = `ai-${nextMsgId()}`
state.messages.push({
id: aiMsgId,
id: aiMsgId as MessageId,
role: 'assistant',
content: '',
timestamp: Date.now(),
@@ -141,7 +141,7 @@ async function regenerate() {
state.messages.pop()
const aiMsgId = `ai-${nextMsgId()}`
state.messages.push({
id: aiMsgId,
id: aiMsgId as MessageId,
role: 'assistant',
content: '',
timestamp: Date.now(),
@@ -211,7 +211,7 @@ async function editMessage(newMessage: string) {
// push 空气泡占位(新 AI 回复将流入)
const aiMsgId = `ai-${nextMsgId()}`
state.messages.push({
id: aiMsgId,
id: aiMsgId as MessageId,
role: 'assistant',
content: '',
timestamp: Date.now(),

View File

@@ -14,6 +14,7 @@
import { state } from '@/stores/ai'
import { t } from '@/i18n/i18n-helpers'
import { nextMsgId, getConvState } from './aiShared'
import type { MessageId } from '@/api/types'
import { forceResetStreaming } from './streamingGuard'
import { emit } from '@tauri-apps/api/event'
@@ -124,7 +125,7 @@ export function onStreamTimeout(convId?: string) {
? t('ai.streamInterruptedAfterTool')
: t('ai.streamInterrupted')
state.messages.push({
id: `timeout-${nextMsgId()}`,
id: `timeout-${nextMsgId()}` as MessageId,
role: 'assistant',
content,
isError: true,

View File

@@ -11,6 +11,7 @@
import { invoke } from '@tauri-apps/api/core'
import { state } from '@/stores/ai'
import { nextMsgId, getConvState, convStates } from './aiShared'
import type { MessageId } from '@/api/types'
import { setStreaming } from './streamingGuard'
import { persistUiState } from './useAiPanel'
@@ -194,7 +195,7 @@ export async function restoreGeneratingState(opts?: { fromMainPanel?: boolean; c
state.currentText = (opts?.convId && localStorage.getItem(textKey(opts.convId))) || localStorage.getItem('df-ai-text') || ''
}
state.messages.push({
id: `ai-${nextMsgId()}`,
id: `ai-${nextMsgId()}` as MessageId,
role: 'assistant',
content: '',
timestamp: Date.now(),