import type { AgentNodeData } from '../types/agentNode' import type { AgentDetailData, ThinkingItem } from '../types/agentDetail' import type { DashboardAgentDto, ModelDto } from '../services/agentService' const STATUS_LABELS: Record = { work: 'Arbeitet', think: 'Plant', idle: 'Bereit', block: 'Blockiert', } interface CatalogEntry { elapsed: string think: string | null next: string } const AGENT_CATALOG: Record = { iris: { elapsed: '--', think: null, next: 'Standby' }, programmer: { elapsed: '--', think: null, next: 'Standby' }, developer: { elapsed: '--', think: null, next: 'Standby' }, architekt: { elapsed: '--', think: null, next: 'Standby' }, reviewer: { elapsed: '--', think: null, next: 'Standby' }, executor: { elapsed: '--', think: null, next: 'Standby' }, researcher: { elapsed: '--', think: null, next: 'Standby' }, } function resolveStatus(isActive: boolean, currentTask: string | null): AgentNodeData['status'] { if (!isActive) return 'idle' if (currentTask && currentTask !== 'Idle') return 'work' return 'think' } function resolveAvatar(id: string, name: string): string { if (id === 'iris') return 'IR' if (id === 'programmer' || id === 'developer') return '' return name.slice(0, 2).toUpperCase() } function buildThinkingItems(data: AgentNodeData): ThinkingItem[] { if (!data.think) return [] const now = new Date() const ts = (ago: number) => { const d = new Date(now.getTime() - ago * 1000) return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' }) } const sentences = data.think.split(/[.…!?]+/).filter(s => s.trim().length > 5) if (sentences.length >= 2) { const items: ThinkingItem[] = [ { type: 'thought', text: sentences[0].trim() + '.', ts: ts(30) }, { type: 'action', text: sentences[1].trim() + '…', ts: ts(18) }, ] const lastSentence = sentences.length >= 3 ? sentences[sentences.length - 1].trim() + '.' : 'Verarbeitung abgeschlossen.' items.push({ type: 'result', text: lastSentence, ts: ts(3) }) return items } if (sentences.length === 1) { return [ { type: 'thought', text: sentences[0].trim(), ts: ts(15) }, { type: 'action', text: 'Analysiere Daten und erstelle nächsten Schritt…', ts: ts(6) }, ] } return [{ type: 'thought', text: data.think, ts: ts(10) }] } export function toAgentNode(dto: DashboardAgentDto): AgentNodeData { const cat = AGENT_CATALOG[dto.id] ?? AGENT_CATALOG['reviewer']! const status = resolveStatus(dto.isActive, dto.currentTask) return { id: dto.id, name: dto.name, role: dto.role, model: dto.model, avatar: resolveAvatar(dto.id, dto.name), status, statusLabel: STATUS_LABELS[status], task: dto.currentTask, goal: dto.goal ?? null, progress: dto.progress ?? 0, elapsed: cat.elapsed, next: cat.next, tokens: '0', cost: '0.00', think: cat.think, } } export function toModelAlias(dtos: ModelDto[]): { id: string; alias: string }[] { return dtos.map(m => ({ id: m.id, alias: m.name })) } export function toAgentDetail( data: AgentNodeData, models: { id: string; alias: string }[] ): AgentDetailData { const tokenNum = parseFloat(data.tokens?.replace(/[^0-9.]/g, '') || '0') const tokenMultiplier = data.tokens?.includes('M') ? 1_000_000 : data.tokens?.includes('k') ? 1_000 : 1 const tokensToday = Math.round(tokenNum * tokenMultiplier) const matchingModel = models.find(m => m.id === data.model || m.alias === data.model) const displayModel = matchingModel?.alias ?? data.model return { id: data.id, name: data.name, role: data.role, model: displayModel, status: data.status === 'block' ? 'idle' : data.status, tokensToday, costToday: parseFloat(data.cost || '0'), workload: data.progress, uptime: data.elapsed || '—', lastActive: data.elapsed !== '—' ? 'Vor ' + data.elapsed : 'Nicht aktiv', activeTaskCount: data.task ? 1 : 0, thinking: buildThinkingItems(data), availableModels: models, } }