/** * Admin Channel Monitor API endpoints * Handles channel monitor (uptime/health) management for administrators */ import { apiClient } from '../client' export type Provider = 'openai' | 'anthropic' | 'gemini' export type MonitorStatus = 'operational' | 'degraded' | 'failed' | 'error' export type BodyOverrideMode = 'off' | 'merge' | 'replace' export interface ChannelMonitor { id: number name: string provider: Provider endpoint: string api_key_masked: string /** * True when the stored encrypted API key cannot be decrypted (e.g. the * encryption key has changed). Admin must re-edit the monitor to provide * a fresh key. Backend skips checks for these monitors. */ api_key_decrypt_failed?: boolean primary_model: string extra_models: string[] group_name: string enabled: boolean interval_seconds: number last_checked_at: string | null created_by: number created_at: string updated_at: string /** Latest status of the primary model (empty when no history yet) */ primary_status: MonitorStatus | '' /** Latest latency of the primary model in ms (null when no history yet) */ primary_latency_ms: number | null /** Primary model 7-day availability percentage (0-100) */ availability_7d: number /** Latest status per extra model (used for hover tooltip) */ extra_models_status: ExtraModelStatus[] /** 请求自定义快照字段(高级设置) */ template_id: number | null extra_headers: Record body_override_mode: BodyOverrideMode body_override: Record | null } export interface ExtraModelStatus { model: string status: MonitorStatus | '' latency_ms: number | null } export interface ListParams { page?: number page_size?: number provider?: Provider enabled?: boolean search?: string } export interface ListResponse { items: ChannelMonitor[] total: number page: number page_size: number pages: number } export interface CreateParams { name: string provider: Provider endpoint: string api_key: string primary_model: string extra_models?: string[] group_name?: string enabled?: boolean interval_seconds: number template_id?: number | null extra_headers?: Record body_override_mode?: BodyOverrideMode body_override?: Record | null } // Update request: api_key 空串 = 不修改;clear_template=true 时把 template_id 置空 export type UpdateParams = Partial & { clear_template?: boolean } export interface CheckResult { model: string status: MonitorStatus latency_ms: number | null ping_latency_ms: number | null message: string checked_at: string } export interface RunNowResponse { results: CheckResult[] } export interface HistoryItem { id: number model: string status: MonitorStatus latency_ms: number | null ping_latency_ms: number | null message: string checked_at: string } export interface HistoryParams { model?: string limit?: number } export interface HistoryResponse { items: HistoryItem[] } /** * List channel monitors with pagination and filters */ export async function list( params: ListParams = {}, options?: { signal?: AbortSignal } ): Promise { const { data } = await apiClient.get('/admin/channel-monitors', { params, signal: options?.signal, }) return data } /** * Get a channel monitor by ID */ export async function get(id: number): Promise { const { data } = await apiClient.get(`/admin/channel-monitors/${id}`) return data } /** * Create a new channel monitor */ export async function create(params: CreateParams): Promise { const { data } = await apiClient.post('/admin/channel-monitors', params) return data } /** * Update an existing channel monitor. * api_key field: empty string means "do not modify". */ export async function update(id: number, params: UpdateParams): Promise { const { data } = await apiClient.put(`/admin/channel-monitors/${id}`, params) return data } /** * Delete a channel monitor */ export async function del(id: number): Promise { await apiClient.delete(`/admin/channel-monitors/${id}`) } /** * Trigger an immediate manual check for a channel monitor. * Returns the latest check results for primary + extra models. */ export async function runNow(id: number): Promise { const { data } = await apiClient.post(`/admin/channel-monitors/${id}/run`) return data } /** * List historical check results for a monitor. */ export async function listHistory( id: number, params: HistoryParams = {} ): Promise { const { data } = await apiClient.get( `/admin/channel-monitors/${id}/history`, { params } ) return data } export const channelMonitorAPI = { list, get, create, update, del, runNow, listHistory, } export default channelMonitorAPI