File size: 1,833 Bytes
d47b053 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | import type { StudioApiEnvelope } from '../protocol/studio-agent-types'
const STUDIO_API_BASE = '/api/studio-agent'
export class StudioApiRequestError extends Error {
readonly code: string
readonly details?: unknown
constructor(message: string, code = 'STUDIO_REQUEST_FAILED', details?: unknown) {
super(message)
this.name = 'StudioApiRequestError'
this.code = code
this.details = details
}
}
export function getStudioApiBase(): string {
return STUDIO_API_BASE
}
export function getStudioAuthHeaders(contentType?: string): HeadersInit {
const headers: HeadersInit = {}
if (contentType) {
headers['Content-Type'] = contentType
}
const apiKey = localStorage.getItem('manimcat_api_key')
if (apiKey) {
headers.Authorization = `Bearer ${apiKey}`
}
return headers
}
export async function studioRequest<T>(path: string, init?: RequestInit): Promise<T> {
const response = await fetch(`${STUDIO_API_BASE}${path}`, init)
const payload = await parseStudioEnvelope<T>(response)
if (!response.ok || !payload.ok) {
if (payload.ok) {
throw new StudioApiRequestError(`Studio request failed with status ${response.status}`)
}
throw new StudioApiRequestError(payload.error.message, payload.error.code, payload.error.details)
}
return payload.data
}
async function parseStudioEnvelope<T>(response: Response): Promise<StudioApiEnvelope<T>> {
const raw = await response.text()
try {
return JSON.parse(raw) as StudioApiEnvelope<T>
} catch {
const snippet = raw.trim().slice(0, 240)
throw new StudioApiRequestError(
snippet
? `Studio API returned invalid JSON (${response.status}): ${snippet}`
: `Studio API returned invalid JSON (${response.status})`
)
}
}
|