5a3a099b94
- Iris zu agents[] hinzugefügt (Position 0) - hero-id='iris' an TeamNetwork übergeben - Hero-Slot data-agent-id dynamisch (:data-agent-id='hero.id')
319 lines
9.2 KiB
TypeScript
319 lines
9.2 KiB
TypeScript
import { ref, reactive, computed } from 'vue'
|
|
|
|
export interface AgentNodeData {
|
|
id: string
|
|
name: string
|
|
role: string
|
|
description: string
|
|
color: string
|
|
icon: string
|
|
currentTask: string
|
|
goal: string
|
|
progress: number
|
|
workload: number // 0-100
|
|
active: boolean
|
|
runtimeSeconds: number
|
|
workingFeed: string[]
|
|
}
|
|
|
|
export interface MissionData {
|
|
id: string
|
|
name: string
|
|
progress: number
|
|
currentTask: string
|
|
lastActivity: string
|
|
remainingTasks: number
|
|
status: 'healthy' | 'attention' | 'blocked' | 'paused'
|
|
}
|
|
|
|
export interface FeedEntry {
|
|
time: string
|
|
agent: string
|
|
action: string
|
|
timestamp: number
|
|
}
|
|
|
|
export interface ChatMessage {
|
|
id: string
|
|
sender: 'user' | 'iris'
|
|
text: string
|
|
timestamp: number
|
|
}
|
|
|
|
export interface QueueItem {
|
|
id: string
|
|
text: string
|
|
priority: 'high' | 'medium' | 'low'
|
|
waitTime: string
|
|
}
|
|
|
|
const now = Date.now()
|
|
|
|
export function useDashboardData() {
|
|
const sessionStart = Date.now()
|
|
|
|
// Runtime counter
|
|
const runtimeSeconds = ref(0)
|
|
let runtimeInterval: ReturnType<typeof setInterval> | null = null
|
|
|
|
function startRuntime() {
|
|
const startTs = sessionStart
|
|
runtimeSeconds.value = Math.floor((Date.now() - startTs) / 1000)
|
|
runtimeInterval = setInterval(() => {
|
|
runtimeSeconds.value = Math.floor((Date.now() - startTs) / 1000)
|
|
}, 1000)
|
|
}
|
|
|
|
function stopRuntime() {
|
|
if (runtimeInterval) {
|
|
clearInterval(runtimeInterval)
|
|
runtimeInterval = null
|
|
}
|
|
}
|
|
|
|
const formatRuntime = (seconds: number): string => {
|
|
const m = Math.floor(seconds / 60)
|
|
const s = seconds % 60
|
|
return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`
|
|
}
|
|
|
|
const irisRuntime = computed(() => formatRuntime(runtimeSeconds.value))
|
|
|
|
// Agent runtimes (simulated)
|
|
const agentStartTimes = reactive<Record<string, number>>({
|
|
iris: now - 28800000,
|
|
developer: now - 3600000,
|
|
devops: now - 1800000,
|
|
researcher: now - 2700000,
|
|
reviewer: now - 900000,
|
|
})
|
|
|
|
const getAgentRuntime = (id: string): string => {
|
|
const start = agentStartTimes[id]
|
|
if (!start) return '00:00'
|
|
const secs = Math.floor((now - start) / 1000)
|
|
const m = Math.floor(secs / 60)
|
|
const s = secs % 60
|
|
return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`
|
|
}
|
|
|
|
// Agents
|
|
const agents = ref<AgentNodeData[]>([
|
|
{
|
|
id: 'iris',
|
|
name: 'Iris',
|
|
role: 'Chief of Staff',
|
|
description: 'Koordiniert, delegiert, hält das Team tight. Die erste Anlaufstelle zwischen Boss und Maschine.',
|
|
color: '#8b7cf6',
|
|
icon: 'bot',
|
|
currentTask: 'Orchestrating Nexus Dashboard redesign',
|
|
goal: 'Complete Mission Control v3',
|
|
progress: 85,
|
|
workload: 55,
|
|
active: true,
|
|
runtimeSeconds: 28800,
|
|
workingFeed: [
|
|
'Analyzed user feedback on Dashboard',
|
|
'Delegated card redesign to Developer',
|
|
'Verifying full-width layout deployment',
|
|
'Reviewing AgentModal integration',
|
|
],
|
|
},
|
|
{
|
|
id: 'developer',
|
|
name: 'Developer',
|
|
role: 'Backend & Frontend',
|
|
description: 'Implements features across the stack with TypeScript, C#, and Vue.',
|
|
color: '#3b82f6',
|
|
icon: 'code',
|
|
currentTask: 'Building Dungeon System API endpoints',
|
|
goal: 'Complete Dungeon CRUD + room generation',
|
|
progress: 62,
|
|
workload: 65,
|
|
active: true,
|
|
runtimeSeconds: 3600,
|
|
workingFeed: [
|
|
'Created DungeonController',
|
|
'Defined dungeon schema',
|
|
'Implementing room generation algorithm',
|
|
'Writing unit tests for RoomFactory',
|
|
],
|
|
},
|
|
{
|
|
id: 'devops',
|
|
name: 'DevOps',
|
|
role: 'Infrastructure & CI/CD',
|
|
description: 'Manages Docker, deployment pipelines, and system reliability.',
|
|
color: '#eab308',
|
|
icon: 'server',
|
|
currentTask: 'Optimizing Docker Compose caching',
|
|
goal: 'Reduce build times by 40%',
|
|
progress: 45,
|
|
workload: 40,
|
|
active: false,
|
|
runtimeSeconds: 1800,
|
|
workingFeed: [
|
|
'Analyzed Docker layer cache',
|
|
'Optimized COPY order in Dockerfile',
|
|
'Added .dockerignore for node_modules',
|
|
'Testing incremental builds',
|
|
],
|
|
},
|
|
{
|
|
id: 'researcher',
|
|
name: 'Researcher',
|
|
role: 'Analysis & Documentation',
|
|
description: 'Researches APIs, patterns, and best practices. Maintains docs.',
|
|
color: '#22c55e',
|
|
icon: 'search',
|
|
currentTask: 'Analyzing WebSocket alternatives',
|
|
goal: 'Recommend real-time communication strategy',
|
|
progress: 30,
|
|
workload: 25,
|
|
active: true,
|
|
runtimeSeconds: 2700,
|
|
workingFeed: [
|
|
'Evaluated WebSocket vs SSE vs WebRTC',
|
|
'Documented SignalR limitations',
|
|
'Prototyping WebSocket fallback',
|
|
],
|
|
},
|
|
{
|
|
id: 'reviewer',
|
|
name: 'Reviewer',
|
|
role: 'Code Quality & Testing',
|
|
description: 'Reviews pull requests, enforces standards, runs test suites.',
|
|
color: '#a855f7',
|
|
icon: 'shield',
|
|
currentTask: 'Reviewing Dungeon System PR',
|
|
goal: 'Zero critical findings before merge',
|
|
progress: 80,
|
|
workload: 50,
|
|
active: false,
|
|
runtimeSeconds: 900,
|
|
workingFeed: [
|
|
'Reviewed DungeonController.cs',
|
|
'Found 3 minor style issues',
|
|
'Approved RoomValidator',
|
|
'Running integration tests',
|
|
],
|
|
},
|
|
])
|
|
|
|
// Missions
|
|
const missions = ref<MissionData[]>([
|
|
{
|
|
id: 'dungeon-system',
|
|
name: 'Dungeon System',
|
|
progress: 62,
|
|
currentTask: 'Implement room generation',
|
|
lastActivity: '3 min ago',
|
|
remainingTasks: 8,
|
|
status: 'healthy',
|
|
},
|
|
{
|
|
id: 'dashboard-redesign',
|
|
name: 'Dashboard Redesign',
|
|
progress: 45,
|
|
currentTask: 'AI Team Network layout',
|
|
lastActivity: 'Just now',
|
|
remainingTasks: 6,
|
|
status: 'healthy',
|
|
},
|
|
{
|
|
id: 'infra-optimization',
|
|
name: 'Infra Optimization',
|
|
progress: 30,
|
|
currentTask: 'Optimize build caching',
|
|
lastActivity: '12 min ago',
|
|
remainingTasks: 4,
|
|
status: 'attention',
|
|
},
|
|
{
|
|
id: 'auth-system',
|
|
name: 'Auth System',
|
|
progress: 88,
|
|
currentTask: 'Finalize refresh token flow',
|
|
lastActivity: '45 min ago',
|
|
remainingTasks: 2,
|
|
status: 'healthy',
|
|
},
|
|
])
|
|
|
|
// Feed
|
|
const feedEntries = ref<FeedEntry[]>([
|
|
{ time: '20:42', agent: 'Developer', action: 'Created DungeonController endpoints', timestamp: now - 60000 },
|
|
{ time: '20:38', agent: 'DevOps', action: 'Optimized Docker COPY order', timestamp: now - 300000 },
|
|
{ time: '20:35', agent: 'Iris', action: 'Delegated room generation to Developer', timestamp: now - 540000 },
|
|
{ time: '20:28', agent: 'Researcher', action: 'Documented WebSocket vs SSE analysis', timestamp: now - 780000 },
|
|
{ time: '20:22', agent: 'Reviewer', action: 'Approved RoomValidator PR', timestamp: now - 900000 },
|
|
{ time: '20:15', agent: 'DevOps', action: 'Added .dockerignore for node_modules', timestamp: now - 1200000 },
|
|
{ time: '20:08', agent: 'Iris', action: 'Broke down Dungeon System tasks', timestamp: now - 1500000 },
|
|
{ time: '19:55', agent: 'Developer', action: 'Defined dungeon schema models', timestamp: now - 1800000 },
|
|
])
|
|
|
|
// Chat
|
|
const chatMessages = ref<ChatMessage[]>([
|
|
{ id: 'm1', sender: 'iris', text: 'Guten Abend, Bao. Ready to continue the Dungeon System?', timestamp: now - 600000 },
|
|
{ id: 'm2', sender: 'user', text: "Yes, what's the status?", timestamp: now - 540000 },
|
|
{ id: 'm3', sender: 'iris', text: "Developer is at 62% on room generation. Reviewer approved the schema. I'd recommend focusing on the room connection logic next.", timestamp: now - 480000 },
|
|
])
|
|
|
|
const irisBusy = ref(true)
|
|
const irisFocus = ref('Breaking down Dungeon System for DevOps and Developer')
|
|
|
|
// Queue
|
|
const queue = ref<QueueItem[]>([
|
|
{ id: 'q1', text: 'Deploy latest dashboard build to preview', priority: 'high', waitTime: '2 min' },
|
|
{ id: 'q2', text: 'Review infrastructure cost analysis', priority: 'medium', waitTime: '8 min' },
|
|
{ id: 'q3', text: 'Schedule B2 German lesson review', priority: 'low', waitTime: '15 min' },
|
|
{ id: 'q4', text: 'Update project roadmap document', priority: 'medium', waitTime: '12 min' },
|
|
])
|
|
|
|
function sendChat(text: string): void {
|
|
if (!text.trim()) return
|
|
chatMessages.value.push({
|
|
id: `user-${Date.now()}`,
|
|
sender: 'user',
|
|
text: text.trim(),
|
|
timestamp: Date.now(),
|
|
})
|
|
}
|
|
|
|
function removeQueueItem(id: string): void {
|
|
const idx = queue.value.findIndex(q => q.id === id)
|
|
if (idx !== -1) queue.value.splice(idx, 1)
|
|
}
|
|
|
|
function moveQueueItem(fromIdx: number, toIdx: number): void {
|
|
if (toIdx < 0 || toIdx >= queue.value.length) return
|
|
const [item] = queue.value.splice(fromIdx, 1)
|
|
queue.value.splice(toIdx, 0, item)
|
|
}
|
|
|
|
function changeQueuePriority(id: string, priority: QueueItem['priority']): void {
|
|
const item = queue.value.find(q => q.id === id)
|
|
if (item) item.priority = priority
|
|
}
|
|
|
|
return {
|
|
agents,
|
|
missions,
|
|
feedEntries,
|
|
chatMessages,
|
|
irisBusy,
|
|
irisFocus,
|
|
irisRuntime,
|
|
queue,
|
|
runtimeSeconds,
|
|
getAgentRuntime,
|
|
startRuntime,
|
|
stopRuntime,
|
|
formatRuntime,
|
|
sendChat,
|
|
removeQueueItem,
|
|
moveQueueItem,
|
|
changeQueuePriority,
|
|
}
|
|
}
|