feat: board-first orchestration with Gateway Bridge, live-update, and flow-board
CI - Build & Test / Backend (.NET) (push) Successful in 1m19s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 18s
CI - Build & Test / Security Check (push) Successful in 3s

- GatewayBridgeController: MCP-artiger Kommando-Adapter für Agent-zu-Backend
- TaskBridgeService + LiveUpdateService: SSE Live-Sync + Bridge-Kommandos
- FlowBoard.vue: Board-first orchestration dashboard panel
- live-sync.ts store + live.ts service: SSE-basierte Live-Updates
- Nullability-Warnung in HealthController.cs gefixt
- nginx.conf: SSE-Proxy + CORS für Bridge-Endpunkte
- .gitignore: pnpm/corepack local caches ausgeschlossen
- docs: architecture-board-first-orchestration.md hinzugefügt
- README: Backend Bridge API dokumentiert
This commit is contained in:
2026-06-22 19:56:45 +02:00
parent de1fc198cb
commit df94ed3cd4
34 changed files with 2115 additions and 118 deletions
+16 -5
View File
@@ -12,11 +12,13 @@
*
* Polling startet bei Mount, stoppt bei Unmount.
*/
import { onMounted, onUnmounted } from 'vue'
import { computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { useAgentStore } from '../../stores/agents'
import { useChatStore } from '../../stores/chat'
import { useDashboardStore } from '../../stores/dashboard'
import { useTaskStore } from '../../stores/tasks'
import { useLiveSyncStore } from '../../stores/live-sync'
import AlertBar from '../../components/dashboard/v2/AlertBar.vue'
import FlowCanvas from '../../components/dashboard/v2/FlowCanvas.vue'
import IrisChat from '../../components/dashboard/v2/IrisChat.vue'
@@ -29,6 +31,8 @@ const agentStore = useAgentStore()
const chatStore = useChatStore()
const dashboardStore = useDashboardStore()
const taskStore = useTaskStore()
const liveSyncStore = useLiveSyncStore()
const router = useRouter()
const {
addAgent,
@@ -42,18 +46,21 @@ const {
updatePositions,
} = useFlowBoardState(agentStore, chatStore)
const blockedTasks = computed(() => taskStore.taskList.filter(task => task.status === 'blocked'))
function handleBlockerClick() {
console.log('[FlowBoard] blocker clicked')
if (!blockedTasks.value.length) return
router.push('/tasks')
}
function blockerLabel() {
const blockedTask = taskStore.taskList.find(task => task.status === 'blocked')
const blockedTask = blockedTasks.value[0]
if (!blockedTask) return undefined
return `${taskStore.taskList.filter(task => task.status === 'blocked').length} Blocker — ${blockedTask.title}`
return `${blockedTasks.value.length} Blocker — ${blockedTask.title}`
}
function blockerCount() {
return taskStore.taskList.filter(task => task.status === 'blocked').length
return blockedTasks.value.length
}
/* ── Lifecycle ────────────────────────────────────── */
@@ -62,6 +69,8 @@ onMounted(() => {
chatStore.startPolling()
dashboardStore.startPolling()
taskStore.startPolling()
taskStore.startBoardPolling()
liveSyncStore.connect()
})
onUnmounted(() => {
@@ -69,6 +78,8 @@ onUnmounted(() => {
chatStore.stopPolling()
dashboardStore.stopPolling()
taskStore.stopPolling()
taskStore.stopBoardPolling()
liveSyncStore.disconnect()
})
</script>