Files
llm-in-text/src/utils/api.js

97 lines
2.7 KiB
JavaScript
Raw Normal View History

import { API_URL } from './config.js'
let cachedIP = null
async function getClientIP() {
if (cachedIP) return cachedIP
try {
const controller = new AbortController()
setTimeout(() => controller.abort(), 3000)
const res = await fetch('https://api.ipify.org?format=json', { signal: controller.signal })
const data = await res.json()
cachedIP = data.ip
return cachedIP
} catch {
return null
}
}
import { useSettingsStore } from '../stores/settings'
export async function fetchSuggestion(prefix, suffix, signal, apiUrl = API_URL) {
try {
const settings = useSettingsStore()
const clientIP = await getClientIP()
const headers = { 'Content-Type': 'application/json' }
// Only send IP if privacy mode is OFF
if (clientIP && !settings.privacyMode) {
headers['X-Client-IP'] = clientIP
}
const body = {
prefix,
suffix,
languageId: 'markdown',
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 reader = res.body?.getReader()
if (!reader) {
throw new Error('No reader available')
}
let text = ''
let buffer = ''
while (true) {
const { done, value } = await reader.read()
if (done) break
buffer += new TextDecoder().decode(value)
const lines = buffer.split('\n')
buffer = lines.pop() || ''
for (const line of lines) {
if (!line.startsWith('data: ')) continue
const jsonStr = line.slice(6).trim()
if (!jsonStr) continue
try {
const data = JSON.parse(jsonStr)
if (data.content) {
text += data.content
}
if (data.done || data.error) break
} catch (e) {
// skip invalid lines
}
}
}
return text
} catch (e) {
if (e.name === 'AbortError') {
// ignore abort
} else {
throw e
}
}
}