import { buildFinanceChatMessages, buildTransactionEnrichmentMessages, } from '../../lib/aiPrompt.js' import { useSettingsStore } from '../../stores/settings.js' import { applyAiEnrichment, fetchRecentTransactionsForAi, markTransactionAiFailed, markTransactionAiRunning, } from '../transactionService.js' import { DeepSeekProvider } from './deepseekProvider.js' const clampThreshold = (value) => { const numeric = Number(value) if (!Number.isFinite(numeric)) return 0.9 return Math.min(Math.max(numeric, 0), 1) } const createProvider = (settingsStore) => { if (settingsStore.aiProvider !== 'deepseek') { throw new Error(`Unsupported AI provider: ${settingsStore.aiProvider}`) } return new DeepSeekProvider({ apiKey: settingsStore.aiApiKey, model: settingsStore.aiModel, }) } export const hasAiAccess = (settingsStore = useSettingsStore()) => !!settingsStore.aiApiKey export const isAiReady = (settingsStore = useSettingsStore()) => !!settingsStore.aiAutoCategoryEnabled && hasAiAccess(settingsStore) export const maybeEnrichTransactionWithAi = async (transaction, options = {}) => { if (!transaction?.id || transaction.entryType === 'transfer') return transaction const settingsStore = useSettingsStore() if (!isAiReady(settingsStore)) { return transaction } try { const running = await markTransactionAiRunning(transaction.id, settingsStore.aiModel) if (running) { options.onProgress?.(running) } const provider = createProvider(settingsStore) const similarTransactions = await fetchRecentTransactionsForAi(6, transaction.id) const messages = buildTransactionEnrichmentMessages({ transaction, similarTransactions: similarTransactions.filter((item) => item.entryType !== 'transfer'), }) const result = await provider.enrichTransaction({ messages }) const threshold = clampThreshold(settingsStore.aiAutoApplyThreshold) const updated = await applyAiEnrichment(transaction.id, result.normalized, { applyCategory: result.normalized.confidence >= threshold, model: result.model, }) return updated || transaction } catch (error) { console.warn('[ai] transaction enrichment failed', error) const failed = await markTransactionAiFailed( transaction.id, error?.message || 'AI enrichment failed', settingsStore.aiModel, ) return failed || transaction } } export const askFinanceAssistant = async ({ question, transactions = [], conversation = [] }) => { const settingsStore = useSettingsStore() if (!hasAiAccess(settingsStore)) { throw new Error('请先在设置页填写 DeepSeek API Key') } const provider = createProvider(settingsStore) const messages = buildFinanceChatMessages({ question, transactions, conversation, }) return provider.chat({ messages }) }