import { Injectable, Logger } from '@nestjs/common'; import type { AiChatDto } from './dto/ai-chat.dto'; import { AdminConversationService } from '../admin-conversation/admin-conversation.service'; const HERMES_API_URL = 'http://10.2.0.7:8642/v1/chat/completions'; const HERMES_API_KEY = 'zhixi-hermes-key-2026'; @Injectable() export class AdminAiChatService { private readonly logger = new Logger(AdminAiChatService.name); constructor(private readonly conversationService: AdminConversationService) {} async chat(dto: AiChatDto, adminUserId: string) { const sessionId = dto.conversationId ? await this.conversationService.getSessionId(dto.conversationId, adminUserId) : null; // Auto-create conversation if none provided const conversationId = dto.conversationId ?? (await this.conversationService.create(adminUserId)).id; // Save user message const userMsg = dto.messages[dto.messages.length - 1]; if (userMsg && userMsg.role === 'user') { await this.conversationService.saveMessage(conversationId, 'user', userMsg.content); } const result = await this.callHermes(dto.messages, sessionId); // Save assistant reply await this.conversationService.saveMessage(conversationId, 'assistant', result.content); return { ...result, conversationId }; } private async callHermes( messages: Array<{ role: string; content: string }>, sessionId: string | null, ) { const start = Date.now(); const headers: Record = { 'Content-Type': 'application/json', Authorization: 'Bearer ' + HERMES_API_KEY, }; if (sessionId) { headers['X-Hermes-Session-Id'] = sessionId; } const resp = await fetch(HERMES_API_URL, { method: 'POST', headers, body: JSON.stringify({ model: 'hermes-agent', messages, temperature: 0.7, max_tokens: 4096, }), signal: AbortSignal.timeout(120_000), }); if (!resp.ok) { const text = await resp.text().catch(() => ''); throw new Error(`Hermes API error ${resp.status}: ${text}`); } const data = await resp.json(); const content = data.choices?.[0]?.message?.content || ''; const usage = data.usage || {}; this.logger.log('Hermes chat: ' + (Date.now() - start) + 'ms, tokens: ' + (usage.prompt_tokens || 0) + '/' + (usage.completion_tokens || 0)); return { content, usage: { model: 'hermes-agent', inputTokens: usage.prompt_tokens, outputTokens: usage.completion_tokens } }; } getDashboardConfig() { return { url: 'http://10.2.0.7:9119', apiUrl: 'http://10.2.0.7:8642/v1', description: 'Hermes Agent Dashboard — 4核4G 上的 AI Agent', }; } }