Files
nexus/frontend/src/mappers/agentMapper.ts
T
reviewer 358ec3e65d
CI - Build & Test / Backend (.NET) (push) Failing after 23s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 15s
CI - Build & Test / Security Check (push) Successful in 3s
feat(frontend): Dashboard V2 — FlowCanvas, AgentModal, IrisChat, Stores, PlaceholderViews, Icon-Library
2026-06-13 20:58:53 +02:00

124 lines
4.1 KiB
TypeScript

import type { AgentNodeData } from '../types/agentNode'
import type { AgentDetailData, ThinkingItem } from '../types/agentDetail'
import type { DashboardAgentDto, ModelDto } from '../services/agentService'
const STATUS_LABELS: Record<AgentNodeData['status'], string> = {
work: 'Arbeitet',
think: 'Plant',
idle: 'Bereit',
block: 'Blockiert',
}
interface CatalogEntry {
elapsed: string
think: string | null
next: string
}
const AGENT_CATALOG: Record<string, CatalogEntry> = {
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,
}
}