fix(shadcn): isolate Nexus CSS vars with --nx- prefix + admin password reset endpoint
This commit is contained in:
@@ -74,6 +74,8 @@ interface DashboardAgentInfo {
|
||||
model: string
|
||||
isActive: boolean
|
||||
currentTask: string
|
||||
description?: string
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
interface DashboardOperationEntry {
|
||||
@@ -105,65 +107,88 @@ interface DashboardQueueItem {
|
||||
|
||||
const AGENT_CATALOG: Record<string, Partial<AgentNodeData>> = {
|
||||
iris: {
|
||||
description: 'Koordiniert, delegiert, hält das Team tight. Die erste Anlaufstelle zwischen Boss und Maschine.',
|
||||
tags: ['Orchestration', 'Delegation', 'Approval'],
|
||||
description: 'Zentrale operative Führungsinstanz. Strukturiert Aufgaben, bewertet Risiken, steuert spezialisierte Agenten und eskaliert kritische Entscheidungen.',
|
||||
tags: ['Orchestration', 'Delegation', 'Approval', 'Risk Management'],
|
||||
color: '#8b7cf6',
|
||||
icon: 'bot',
|
||||
hero: true,
|
||||
goal: 'Complete Mission Control v3',
|
||||
goal: 'Mission Control — maximale Autonomie bei kontrolliertem Risiko',
|
||||
progress: 90,
|
||||
workload: 60,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
developer: {
|
||||
description: 'Primärer Entwicklungsagent. Implementiert Features, behebt Bugs und schreibt Code im gesamten Stack — autonom im Rahmen seines Scopes.',
|
||||
tags: ['Full-Stack', 'TypeScript', 'C#', 'Vue', '.NET', 'Builds'],
|
||||
color: '#3b82f6',
|
||||
icon: 'code',
|
||||
goal: 'Nexus Dashboard & Dungeon System',
|
||||
progress: 70,
|
||||
workload: 65,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
architekt: {
|
||||
description: 'Verwaltet die gesamte Server-Infrastruktur. Deployt Services, konfiguriert Docker, Nginx und Firewall. Stellt sicher, dass die Produktivumgebung stabil und sicher läuft.',
|
||||
tags: ['Docker', 'Nginx', 'CI/CD', 'Firewall', 'VPS'],
|
||||
color: '#eab308',
|
||||
icon: 'server',
|
||||
goal: 'Stabile Zero-Downtime-Deployments',
|
||||
progress: 60,
|
||||
workload: 45,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
researcher: {
|
||||
description: 'Spezialisierter Recherche-Agent. Sucht online, prüft Quellen, analysiert Inhalte (inkl. YouTube-Videos) und übergibt strukturierte Erkenntnisse. Ausschließlich Lese- und Analyse-Rechte.',
|
||||
tags: ['Research', 'Quellenprüfung', 'Analyse', 'Docs'],
|
||||
color: '#22c55e',
|
||||
icon: 'search',
|
||||
goal: 'Verifizierte, strukturierte Recherche-Ergebnisse',
|
||||
progress: 40,
|
||||
workload: 30,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
reviewer: {
|
||||
description: 'Code-Qualitätskontrolle. Prüft Diffs auf Bugs, Regressionen, Sicherheitslücken und Wartbarkeit. Berichtet Findings strukturiert und knapp.',
|
||||
tags: ['Code Review', 'Testing', 'Security', 'Quality'],
|
||||
color: '#a855f7',
|
||||
icon: 'shield',
|
||||
goal: 'Zero critical findings before merge',
|
||||
progress: 85,
|
||||
workload: 55,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
developer: {
|
||||
description: 'Implements features across the stack with TypeScript, C#, and Vue.',
|
||||
tags: ['Coding', 'Development', 'Builds'],
|
||||
executor: {
|
||||
description: 'Einziger Agent mit Host-Exec-Rechten. Führt Docker- und Shell-Befehle auf dem VPS aus — ausschließlich im Auftrag von Iris. Handelt niemals eigeninitiativ.',
|
||||
tags: ['Docker', 'Shell', 'Host', 'Deployment'],
|
||||
color: '#f59e0b',
|
||||
icon: 'server',
|
||||
goal: 'Sichere Host-Execution im Allowlist-Rahmen',
|
||||
progress: 95,
|
||||
workload: 20,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
// Alias: API sends "programmer" but AGENT_CATALOG uses "developer" as canonical key
|
||||
programmer: {
|
||||
description: 'Primärer Entwicklungsagent. Implementiert Features, behebt Bugs und schreibt Code im gesamten Stack — autonom im Rahmen seines Scopes.',
|
||||
tags: ['Full-Stack', 'TypeScript', 'C#', 'Vue', '.NET', 'Builds'],
|
||||
color: '#3b82f6',
|
||||
icon: 'code',
|
||||
goal: 'Complete Dungeon CRUD + room generation',
|
||||
progress: 62,
|
||||
goal: 'Nexus Dashboard & Dungeon System',
|
||||
progress: 70,
|
||||
workload: 65,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
devops: {
|
||||
description: 'Manages Docker, deployment pipelines, and system reliability.',
|
||||
tags: ['Deployment', 'Docker', 'CI/CD'],
|
||||
color: '#eab308',
|
||||
icon: 'server',
|
||||
goal: 'Reduce build times by 40%',
|
||||
progress: 45,
|
||||
workload: 40,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
researcher: {
|
||||
description: 'Researches APIs, patterns, and best practices. Maintains docs.',
|
||||
tags: ['Research', 'Analysis', 'Docs'],
|
||||
color: '#22c55e',
|
||||
icon: 'search',
|
||||
goal: 'Recommend real-time communication strategy',
|
||||
progress: 30,
|
||||
workload: 25,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
reviewer: {
|
||||
description: 'Reviews pull requests, enforces standards, runs test suites.',
|
||||
tags: ['Code Review', 'Testing', 'Quality'],
|
||||
color: '#a855f7',
|
||||
icon: 'shield',
|
||||
goal: 'Zero critical findings before merge',
|
||||
progress: 80,
|
||||
workload: 50,
|
||||
workingFeed: [],
|
||||
thinkingStream: [],
|
||||
},
|
||||
}
|
||||
|
||||
function enrichAgent(api: DashboardAgentInfo): AgentNodeData {
|
||||
const catalog = AGENT_CATALOG[api.id] ?? AGENT_CATALOG['developer']
|
||||
const catalog = AGENT_CATALOG[api.id] ?? AGENT_CATALOG['reviewer']
|
||||
return {
|
||||
id: api.id,
|
||||
name: api.name,
|
||||
@@ -171,8 +196,8 @@ function enrichAgent(api: DashboardAgentInfo): AgentNodeData {
|
||||
model: api.model,
|
||||
currentTask: api.currentTask ?? 'Idle',
|
||||
active: api.isActive,
|
||||
description: catalog.description ?? '',
|
||||
tags: catalog.tags ?? [],
|
||||
description: api.description ?? catalog.description ?? '',
|
||||
tags: api.tags ?? catalog.tags ?? [],
|
||||
color: catalog.color ?? '#6b7385',
|
||||
icon: catalog.icon ?? 'bot',
|
||||
hero: catalog.hero ?? false,
|
||||
@@ -214,6 +239,7 @@ const agents = ref<AgentNodeData[]>([])
|
||||
const chatMessages = ref<ChatMessage[]>([])
|
||||
const irisBusy = ref(false)
|
||||
const irisFocus = ref('')
|
||||
const busySince = ref(0)
|
||||
|
||||
// Operations Feed
|
||||
const feedEntries = ref<FeedEntry[]>([])
|
||||
@@ -330,6 +356,7 @@ async function sendChatMessage(text: string): Promise<void> {
|
||||
})
|
||||
|
||||
irisBusy.value = true
|
||||
busySince.value = Date.now()
|
||||
|
||||
try {
|
||||
const res = await apiFetch('/api/dashboard/chat/send', {
|
||||
@@ -362,6 +389,7 @@ async function sendChatMessage(text: string): Promise<void> {
|
||||
})
|
||||
} finally {
|
||||
irisBusy.value = false
|
||||
busySince.value = 0
|
||||
irisFocus.value = text.trim()
|
||||
}
|
||||
}
|
||||
@@ -457,6 +485,7 @@ export function useDashboardData() {
|
||||
chatMessages,
|
||||
irisBusy,
|
||||
irisFocus,
|
||||
busySince,
|
||||
irisRuntime,
|
||||
queue,
|
||||
gatewayOk,
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
|
||||
export function useTimer() {
|
||||
const elapsed = ref(0)
|
||||
let interval: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
function start() {
|
||||
if (interval !== null) return
|
||||
const startTime = Date.now()
|
||||
elapsed.value = 0
|
||||
interval = setInterval(() => {
|
||||
elapsed.value = Math.floor((Date.now() - startTime) / 1000)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (interval !== null) {
|
||||
clearInterval(interval)
|
||||
interval = null
|
||||
}
|
||||
}
|
||||
|
||||
function format(minutes: number, seconds: number): string {
|
||||
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const formatted = (): string => {
|
||||
const m = Math.floor(elapsed.value / 60)
|
||||
const s = elapsed.value % 60
|
||||
return format(m, s)
|
||||
}
|
||||
|
||||
onMounted(start)
|
||||
onUnmounted(stop)
|
||||
|
||||
return { elapsed, formatted, start, stop }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ref, readonly } from 'vue'
|
||||
import type { Toast } from '../types/toast'
|
||||
|
||||
let nextId = 1
|
||||
const toasts = ref<Toast[]>([])
|
||||
|
||||
export function useToast() {
|
||||
function add(message: string, type: Toast['type'] = 'info', durationMs = 3500) {
|
||||
const id = nextId++
|
||||
toasts.value.push({ id, message, type, durationMs })
|
||||
if (durationMs > 0) {
|
||||
setTimeout(() => remove(id), durationMs)
|
||||
}
|
||||
}
|
||||
|
||||
function remove(id: number) {
|
||||
const idx = toasts.value.findIndex(t => t.id === id)
|
||||
if (idx !== -1) toasts.value.splice(idx, 1)
|
||||
}
|
||||
|
||||
return {
|
||||
toasts: readonly(toasts),
|
||||
success: (msg: string, durationMs?: number) => add(msg, 'success', durationMs),
|
||||
error: (msg: string, durationMs?: number) => add(msg, 'error', durationMs),
|
||||
info: (msg: string, durationMs?: number) => add(msg, 'info', durationMs),
|
||||
remove,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user