diff --git a/src/utils/api.js b/src/utils/api.js index ec64515..4087b81 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -1,4 +1,4 @@ -import { API_URL, API_KEY, PRO_STREAM_URL, TTS_URL, TTS_STATUS_URL, TTS_CONFIG_URL } from './config.js' +import { API_URL, API_KEY, PRO_STREAM_URL, PRO_FRONTEND_TIMEOUT_MS, TTS_URL, TTS_STATUS_URL, TTS_CONFIG_URL } from './config.js' import { useSettingsStore } from '../stores/settings' function generateRequestId() { @@ -20,6 +20,15 @@ function getCancelUrl(apiUrl) { return `${normalized}/cancel` } +function getProCancelUrl(apiUrl) { + const normalized = String(apiUrl || '').replace(/\/+$/, '') + if (!normalized) return '/v1/completions/cancel' + if (/\/v1\/pro\/completions$/i.test(normalized)) { + return normalized.replace(/\/v1\/pro\/completions$/i, '/v1/completions/cancel') + } + return normalized.replace(/\/v1\/pro\/completions\/stream$/i, '/v1/completions/cancel') +} + function normalizeAbortReason(reason) { if (typeof reason === 'string' && reason.trim()) { return reason.trim().slice(0, 64) @@ -158,16 +167,16 @@ export async function fetchProSuggestionStream(payload, apiUrl = PRO_STREAM_URL) prefix = '', suffix = '', languageId = 'markdown', + instruction = '', signal, - model = '', - temperature = 0.7, - timeoutMs = 600000, + timeoutMs = PRO_FRONTEND_TIMEOUT_MS, onChunk, + onEvent, } = payload || {} const settings = useSettingsStore() const requestId = generateRequestId() - const cancelUrl = getCancelUrl(apiUrl) + const cancelUrl = getProCancelUrl(apiUrl) const requestController = new AbortController() const timeoutId = setTimeout(() => { requestController.abort('timeout') @@ -201,10 +210,19 @@ export async function fetchProSuggestionStream(payload, apiUrl = PRO_STREAM_URL) 'X-API-Key': API_KEY, }, body: JSON.stringify( - buildCompletionBody(settings, prefix, suffix, String(languageId || 'markdown').trim() || 'markdown', { - model, - temperature, - }) + { + prefix, + suffix, + languageId: String(languageId || 'markdown').trim() || 'markdown', + instruction, + pro_thinking: settings.proThinking || 'medium', + privacy_mode: settings.privacyMode, + user_preferences: { + language: settings.language, + currency: settings.currency, + timezone: settings.detectedTimezone, + }, + } ), signal: requestController.signal, }) @@ -235,6 +253,18 @@ export async function fetchProSuggestionStream(payload, apiUrl = PRO_STREAM_URL) buffer = buffer.slice(boundary + 2) const parsed = parseSseEvent(chunk) + if (parsed.event && parsed.event !== 'message') { + let eventData = {} + if (parsed.data) { + try { + eventData = JSON.parse(parsed.data) + } catch { + eventData = {} + } + } + onEvent?.(parsed.event, eventData) + } + if (parsed.event === 'chunk' && parsed.data) { const data = JSON.parse(parsed.data) const delta = String(data.delta || '') diff --git a/src/utils/config.js b/src/utils/config.js index 31e76ca..e019aa7 100644 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -5,6 +5,7 @@ const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || DEFAULT_API_BASE_URL export const API_URL = import.meta.env.VITE_API_URL || `${API_BASE_URL}/v1/completions` export const PRO_STREAM_URL = import.meta.env.VITE_PRO_STREAM_URL || `${API_BASE_URL}/v1/pro/completions/stream` +export const PRO_FRONTEND_TIMEOUT_MS = Number(import.meta.env.VITE_PRO_FRONTEND_TIMEOUT_MS || 3660000) export const OCR_URL = import.meta.env.VITE_OCR_URL || `${API_BASE_URL}/v1/ocr` export const CONVERT_URL = import.meta.env.VITE_CONVERT_URL || `${API_BASE_URL}/v1/convert` export const EXPORT_PDF_URL = import.meta.env.VITE_EXPORT_PDF_URL || '/v1/export/pdf'