import { request, getBaseUrlValue, getApiKey } from '../client' export interface HermesProfile { name: string active: boolean model: string gatewayStatus?: string alias: string avatar?: ProfileAvatar | null } export interface HermesProfileDetail { name: string path: string model: string provider: string skills: number hasEnv: boolean hasSoulMd: boolean avatar?: ProfileAvatar | null } export interface ProfileAvatar { type: 'generated' | 'image' seed?: string dataUrl?: string updatedAt?: number } export interface ProfileRuntimeStatus { profile: string bridge: { running: boolean profile: string mode?: string reachable?: boolean error?: string } gateway: { profile: string running: boolean pid?: number port?: number host?: string url?: string error?: string diagnostics?: { health_url?: string reason?: string health_ok?: boolean } } } export interface ProfileRuntimeStatusesResponse { profiles: ProfileRuntimeStatus[] refreshing?: boolean } export async function fetchProfiles(): Promise { const res = await request<{ profiles: HermesProfile[] }>('/api/hermes/profiles') return res.profiles } export async function fetchProfileDetail(name: string): Promise { const res = await request<{ profile: HermesProfileDetail }>(`/api/hermes/profiles/${encodeURIComponent(name)}`) return res.profile } export async function fetchProfileRuntimeStatus(name: string): Promise { return request(`/api/hermes/profiles/${encodeURIComponent(name)}/runtime-status`) } export async function fetchProfileRuntimeStatusesWithMeta(options: { refresh?: boolean } = {}): Promise { const query = options.refresh === false ? '?refresh=0' : '' return request(`/api/hermes/profiles/runtime-statuses${query}`) } export async function fetchProfileRuntimeStatuses(): Promise { const res = await fetchProfileRuntimeStatusesWithMeta() return res.profiles } export async function updateProfileAvatar(name: string, avatar: ProfileAvatar): Promise { const res = await request<{ avatar: ProfileAvatar }>(`/api/hermes/profiles/${encodeURIComponent(name)}/avatar`, { method: 'PUT', body: JSON.stringify(avatar), }) return res.avatar } export async function deleteProfileAvatar(name: string): Promise { await request(`/api/hermes/profiles/${encodeURIComponent(name)}/avatar`, { method: 'DELETE' }) } export async function restartProfileGateway(name: string): Promise { const res = await request<{ success: boolean; gateway: ProfileRuntimeStatus['gateway'] }>( `/api/hermes/profiles/${encodeURIComponent(name)}/gateway/restart`, { method: 'POST' }, ) return res.gateway } export async function restartProfileRuntime(name: string): Promise { const res = await request<{ success: boolean; status: ProfileRuntimeStatus }>( `/api/hermes/profiles/${encodeURIComponent(name)}/restart`, { method: 'POST' }, ) return res.status } export interface CreateProfileResult { success: boolean /** clone=true 时被清理的独占平台凭据 KEY 名 */ strippedCredentials?: string[] /** clone=true 时被禁用的独占平台名 */ disabledPlatforms?: string[] /** clone=true 时在 config.yaml 中被清理的内嵌凭据字段路径 */ strippedConfigCredentials?: string[] } export async function createProfile(name: string, clone?: boolean): Promise { try { const res = await request<{ success: boolean strippedCredentials?: string[] disabledPlatforms?: string[] strippedConfigCredentials?: string[] error?: string }>('/api/hermes/profiles', { method: 'POST', body: JSON.stringify({ name, clone }), }) return { success: !!res.success, strippedCredentials: res.strippedCredentials, disabledPlatforms: res.disabledPlatforms, strippedConfigCredentials: res.strippedConfigCredentials, error: res.error, } } catch (err: any) { return { success: false, error: err.message || 'Unknown error' } } } export async function deleteProfile(name: string): Promise { try { await request(`/api/hermes/profiles/${encodeURIComponent(name)}`, { method: 'DELETE' }) return true } catch { return false } } export async function renameProfile(name: string, newName: string): Promise { try { await request(`/api/hermes/profiles/${encodeURIComponent(name)}/rename`, { method: 'POST', body: JSON.stringify({ new_name: newName }), }) return true } catch { return false } } export async function switchProfile(name: string): Promise { return !!name } export async function switchHermesProfile(name: string): Promise { try { await request('/api/hermes/profiles/active', { method: 'PUT', body: JSON.stringify({ name }), }) return true } catch { return false } } export async function exportProfile(name: string): Promise { try { const baseUrl = getBaseUrlValue() const token = getApiKey() const headers: Record = {} if (token) headers['Authorization'] = `Bearer ${token}` const res = await fetch(`${baseUrl}/api/hermes/profiles/${encodeURIComponent(name)}/export`, { method: 'POST', headers, }) if (!res.ok) throw new Error() const blob = await res.blob() const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `hermes-profile-${name}.tar.gz` a.click() URL.revokeObjectURL(url) return true } catch { return false } } export async function importProfile(file: File): Promise { try { const baseUrl = getBaseUrlValue() const token = getApiKey() const headers: Record = {} if (token) headers['Authorization'] = `Bearer ${token}` const formData = new FormData() formData.append('file', file) const res = await fetch(`${baseUrl}/api/hermes/profiles/import`, { method: 'POST', headers, body: formData, }) return res.ok } catch { return false } }