Download desktop/src/api/client.ts from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 4.91 kB
-
https://huggingface.co/chenbhao/codev/resolve/e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/api/client.ts
- Command line
-
hf download hf://chenbhao/codev@e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/api/client.ts
-
curl -L -o client.ts https://huggingface.co/chenbhao/codev/resolve/e40073cc959cd4729bf4009662bca374c5c4e266/desktop/src/api/client.ts
4.91 kB
| const ENV_BASE_URL = | |
| typeof import.meta !== 'undefined' && | |
| typeof import.meta.env?.VITE_DESKTOP_SERVER_URL === 'string' && | |
| import.meta.env.VITE_DESKTOP_SERVER_URL.length > 0 | |
| ? import.meta.env.VITE_DESKTOP_SERVER_URL | |
| : undefined | |
| const DEFAULT_BASE_URL = ENV_BASE_URL || 'http://127.0.0.1:3456' | |
| let baseUrl = DEFAULT_BASE_URL | |
| let authToken: string | null = null | |
| const DIAGNOSTICS_PATH = '/api/diagnostics/events' | |
| function getErrorMessage(status: number, body: unknown) { | |
| if (body && typeof body === 'object' && 'message' in body && typeof body.message === 'string') { | |
| return body.message | |
| } | |
| if (typeof body === 'string' && body.trim().length > 0) { | |
| return body | |
| } | |
| return `API error ${status}` | |
| } | |
| export function setBaseUrl(url: string) { | |
| baseUrl = url.replace(/\/$/, '') | |
| } | |
| export function getBaseUrl() { | |
| return baseUrl | |
| } | |
| export function getApiUrl(pathOrUrl: string) { | |
| try { | |
| return new URL(pathOrUrl).toString() | |
| } catch { | |
| const normalizedPath = pathOrUrl.startsWith('/') ? pathOrUrl : `/${pathOrUrl}` | |
| return `${baseUrl}${normalizedPath}` | |
| } | |
| } | |
| export function setAuthToken(token: string | null) { | |
| const trimmed = token?.trim() ?? '' | |
| authToken = trimmed.length > 0 ? trimmed : null | |
| } | |
| export function getAuthToken() { | |
| return authToken | |
| } | |
| export function getDefaultBaseUrl() { | |
| return DEFAULT_BASE_URL | |
| } | |
| export function hasExplicitDefaultBaseUrl() { | |
| return Boolean(ENV_BASE_URL) | |
| } | |
| export class ApiError extends Error { | |
| constructor( | |
| public status: number, | |
| public body: unknown, | |
| ) { | |
| super(getErrorMessage(status, body)) | |
| this.name = 'ApiError' | |
| } | |
| } | |
| async function request<T>(method: string, path: string, body?: unknown, options?: { timeout?: number }): Promise<T> { | |
| const url = `${baseUrl}${path}` | |
| const headers = buildHeaders() | |
| const controller = new AbortController() | |
| const timeoutMs = options?.timeout ?? 30_000 | |
| const timeout = setTimeout(() => controller.abort(), timeoutMs) | |
| try { | |
| const res = await fetch(url, { | |
| method, | |
| headers, | |
| body: body !== undefined ? JSON.stringify(body) : undefined, | |
| signal: controller.signal, | |
| }) | |
| clearTimeout(timeout) | |
| if (!res.ok) { | |
| const errorBody = await res.json().catch(() => res.text()) | |
| throw new ApiError(res.status, errorBody) | |
| } | |
| if (res.status === 204) return undefined as T | |
| return res.json() as Promise<T> | |
| } catch (err) { | |
| clearTimeout(timeout) | |
| if (controller.signal.aborted) { | |
| const timeoutError = new Error(`Request timed out after ${Math.round(timeoutMs / 1000)}s`) | |
| reportApiFailure(method, path, timeoutError) | |
| throw timeoutError | |
| } | |
| reportApiFailure(method, path, err) | |
| throw err | |
| } | |
| } | |
| function reportApiFailure(method: string, path: string, error: unknown) { | |
| if (path.startsWith('/api/diagnostics')) return | |
| const details: Record<string, unknown> = { | |
| method, | |
| path, | |
| errorName: error instanceof Error ? error.name : typeof error, | |
| message: sanitizeDiagnosticValue(error instanceof Error ? error.message : String(error)), | |
| } | |
| if (error instanceof ApiError) { | |
| details.status = error.status | |
| details.response = sanitizeDiagnosticValue(error.body) | |
| } | |
| void rawRecordDiagnosticEvent({ | |
| type: 'client_api_request_failed', | |
| severity: 'warn', | |
| summary: `${method} ${path} failed: ${details.message}`, | |
| details, | |
| }) | |
| } | |
| export function rawRecordDiagnosticEvent(event: { | |
| type: string | |
| severity?: 'debug' | 'info' | 'warn' | 'error' | |
| summary: string | |
| sessionId?: string | |
| details?: unknown | |
| }) { | |
| return fetch(`${baseUrl}${DIAGNOSTICS_PATH}`, { | |
| method: 'POST', | |
| headers: buildHeaders(), | |
| body: JSON.stringify(event), | |
| }).catch(() => undefined) | |
| } | |
| function buildHeaders(): Record<string, string> { | |
| const headers: Record<string, string> = { | |
| 'Content-Type': 'application/json', | |
| } | |
| if (authToken) { | |
| headers.Authorization = `Bearer ${authToken}` | |
| } | |
| return headers | |
| } | |
| function sanitizeDiagnosticValue(value: unknown): unknown { | |
| if (!authToken) return value | |
| if (typeof value === 'string') { | |
| return value.split(authToken).join('[redacted]') | |
| } | |
| if (Array.isArray(value)) { | |
| return value.map((entry) => sanitizeDiagnosticValue(entry)) | |
| } | |
| if (value && typeof value === 'object') { | |
| return Object.fromEntries( | |
| Object.entries(value).map(([key, entry]) => [key, sanitizeDiagnosticValue(entry)]), | |
| ) | |
| } | |
| return value | |
| } | |
| export const api = { | |
| get: <T>(path: string, options?: { timeout?: number }) => request<T>('GET', path, undefined, options), | |
| post: <T>(path: string, body?: unknown, options?: { timeout?: number }) => request<T>('POST', path, body, options), | |
| put: <T>(path: string, body?: unknown) => request<T>('PUT', path, body), | |
| patch: <T>(path: string, body?: unknown) => request<T>('PATCH', path, body), | |
| delete: <T>(path: string) => request<T>('DELETE', path), | |
| } | |