01b132266a
Add a file tree UI and corresponding composable for local file management. Introduce TTS menu and player components for voice synthesis integration. Add new EditorView and DocsView routes and update SettingsPanel view switching. Enhance Mermaid plugin with improved styling and action buttons.
149 lines
4.0 KiB
JavaScript
149 lines
4.0 KiB
JavaScript
import { API_URL, API_KEY, TTS_URL, TTS_STATUS_URL } from './config.js'
|
|
import { useSettingsStore } from '../stores/settings'
|
|
|
|
function generateRequestId() {
|
|
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
return crypto.randomUUID()
|
|
}
|
|
return `${Date.now()}-${Math.random().toString(16).slice(2)}`
|
|
}
|
|
|
|
function getCancelUrl(apiUrl) {
|
|
const normalized = String(apiUrl || '').replace(/\/+$/, '')
|
|
if (!normalized) return '/v1/completions/cancel'
|
|
if (normalized.endsWith('/v1/completions')) {
|
|
return `${normalized}/cancel`
|
|
}
|
|
return `${normalized}/cancel`
|
|
}
|
|
|
|
function normalizeAbortReason(reason) {
|
|
if (typeof reason === 'string' && reason.trim()) {
|
|
return reason.trim().slice(0, 64)
|
|
}
|
|
return 'abort'
|
|
}
|
|
|
|
async function sendCancelRequest(cancelUrl, requestId, reason) {
|
|
try {
|
|
await fetch(cancelUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-API-Key': API_KEY,
|
|
},
|
|
body: JSON.stringify({
|
|
request_id: requestId,
|
|
reason,
|
|
}),
|
|
})
|
|
} catch {
|
|
// Cancel request failed silently
|
|
}
|
|
}
|
|
|
|
export async function fetchSuggestion(prefix, suffix, languageId, signal, apiUrl = API_URL) {
|
|
let normalizedLanguageId = 'markdown'
|
|
if (typeof languageId === 'string' && languageId.trim()) {
|
|
normalizedLanguageId = languageId.trim()
|
|
} else if (languageId && typeof languageId === 'object' && 'aborted' in languageId) {
|
|
signal = languageId
|
|
}
|
|
if (typeof signal === 'string') {
|
|
apiUrl = signal
|
|
signal = undefined
|
|
}
|
|
const requestId = generateRequestId()
|
|
const cancelUrl = getCancelUrl(apiUrl)
|
|
|
|
const onAbort = () => {
|
|
const reason = normalizeAbortReason(signal?.reason)
|
|
void sendCancelRequest(cancelUrl, requestId, reason)
|
|
}
|
|
|
|
if (signal) {
|
|
if (signal.aborted) {
|
|
onAbort()
|
|
} else {
|
|
signal.addEventListener('abort', onAbort, { once: true })
|
|
}
|
|
}
|
|
|
|
try {
|
|
const settings = useSettingsStore()
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
'X-Request-Id': requestId,
|
|
'X-API-Key': API_KEY,
|
|
}
|
|
|
|
const body = {
|
|
prefix,
|
|
suffix,
|
|
languageId: normalizedLanguageId,
|
|
model_thinking: settings.modelThinking,
|
|
privacy_mode: settings.privacyMode,
|
|
user_preferences: {
|
|
language: settings.language,
|
|
currency: settings.currency,
|
|
timezone: settings.detectedTimezone,
|
|
},
|
|
}
|
|
|
|
const res = await fetch(apiUrl, {
|
|
method: 'POST',
|
|
headers,
|
|
body: JSON.stringify(body),
|
|
signal,
|
|
})
|
|
|
|
if (!res.ok) {
|
|
const errorText = await res.text()
|
|
throw new Error(`HTTP ${res.status}: ${errorText}`)
|
|
}
|
|
|
|
const data = await res.json()
|
|
return data.content || ''
|
|
} catch (e) {
|
|
if (e.name === 'AbortError') {
|
|
// ignore abort
|
|
} else {
|
|
throw e
|
|
}
|
|
} finally {
|
|
if (signal) {
|
|
signal.removeEventListener('abort', onAbort)
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function fetchTTS(text, voice = 'af_bella', rate = 1.0, apiUrl = TTS_URL) {
|
|
const res = await fetch(apiUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-API-Key': API_KEY,
|
|
},
|
|
body: JSON.stringify({ text, voice, rate, format: 'wav' }),
|
|
})
|
|
|
|
if (!res.ok) {
|
|
const errorText = await res.text()
|
|
throw new Error(`TTS HTTP ${res.status}: ${errorText}`)
|
|
}
|
|
|
|
return res.json()
|
|
}
|
|
|
|
export async function fetchTTSStatus(apiUrl = TTS_STATUS_URL) {
|
|
const res = await fetch(apiUrl, {
|
|
headers: { 'X-API-Key': API_KEY },
|
|
})
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`TTS Status HTTP ${res.status}`)
|
|
}
|
|
|
|
return res.json()
|
|
}
|