feat: Bao/Iris-Statusrechte + Bao→Iris-Notifications + Agent-Workflow-Übersicht
- Bao darf jetzt Status ändern (neben Iris), Sub-Agents weiterhin nicht - CanEditContent für Inhaltsbearbeitung durch alle bekannten Caller - Bao-Content-Änderungen triggern task_content_changed-Notification an Iris - Bao-Status-Änderungen triggern task_status_changed-Notification an Iris - Iris-Status-Änderungen triggern task_status_changed-Notification an Bao - Neue WorkTask-Felder: IsAgentTask (bool), ExpectedFrom (string) - Agent-Workflow-API: CreateAgentTask, WaitingTasks, AgentOverview - Frontend: Agent-Task-Badge, Iris-Overview-Panel, isBao-Getter - Login-Rate-Limiter mit strukturiertem JSON-Fehlermeldungs-Body - Volume-Name: nexus-postgres → postgres-data (Standardisierung)
This commit is contained in:
@@ -25,6 +25,8 @@ export interface DashboardTaskDto {
|
||||
dueDate?: string | null
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
isAgentTask?: boolean
|
||||
expectedFrom?: string | null
|
||||
}
|
||||
|
||||
export interface BoardGroup {
|
||||
@@ -36,6 +38,14 @@ export interface BoardGroup {
|
||||
blocked: DashboardTaskDto[]
|
||||
}
|
||||
|
||||
export interface AgentWorkflowOverview {
|
||||
waitingForBao: DashboardTaskDto[]
|
||||
waitingForIris: DashboardTaskDto[]
|
||||
waitingForOthers: DashboardTaskDto[]
|
||||
staleTasks: DashboardTaskDto[]
|
||||
staleThreshold: string
|
||||
}
|
||||
|
||||
/* ── State Mapping ────────────────────────────────── */
|
||||
|
||||
function mapPriority(priority: string): TaskItem['priority'] {
|
||||
@@ -92,10 +102,28 @@ export const useTaskStore = defineStore('tasks', {
|
||||
} as BoardGroup,
|
||||
boardLoading: false,
|
||||
boardError: null as string | null,
|
||||
|
||||
// Agent Workflow Overview (for Iris)
|
||||
agentOverview: null as AgentWorkflowOverview | null,
|
||||
agentOverviewLoading: false,
|
||||
agentOverviewError: null as string | null,
|
||||
}),
|
||||
|
||||
getters: {
|
||||
taskList: (state) => state.tasks,
|
||||
|
||||
// Iris helpers
|
||||
waitingForIrisTasks: (state) => state.agentOverview?.waitingForIris ?? [],
|
||||
waitingForBaoTasks: (state) => state.agentOverview?.waitingForBao ?? [],
|
||||
waitingForOthersTasks: (state) => state.agentOverview?.waitingForOthers ?? [],
|
||||
staleTasksList: (state) => state.agentOverview?.staleTasks ?? [],
|
||||
agentTaskCount: (state) => {
|
||||
if (!state.agentOverview) return 0
|
||||
return state.agentOverview.waitingForBao.length +
|
||||
state.agentOverview.waitingForIris.length +
|
||||
state.agentOverview.waitingForOthers.length +
|
||||
state.agentOverview.staleTasks.length
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
@@ -267,6 +295,54 @@ export const useTaskStore = defineStore('tasks', {
|
||||
}
|
||||
},
|
||||
|
||||
/* ── API: Fetch agent workflow overview ──────── */
|
||||
async fetchAgentOverview(staleHours = 2) {
|
||||
this.agentOverviewLoading = true
|
||||
try {
|
||||
const res = await apiFetch(`/api/dashboard/tasks/agent-overview?staleHours=${staleHours}`)
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
||||
const data: AgentWorkflowOverview = await res.json()
|
||||
this.agentOverview = data
|
||||
this.agentOverviewError = null
|
||||
} catch (err) {
|
||||
console.warn('[TaskStore] fetchAgentOverview failed', err)
|
||||
this.agentOverviewError = 'Agent overview could not be loaded'
|
||||
} finally {
|
||||
this.agentOverviewLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
/* ── API: Create agent task ───────────────────── */
|
||||
async createAgentTask(data: {
|
||||
title: string
|
||||
detail?: string | null
|
||||
source?: string
|
||||
priority?: string
|
||||
assignedTo?: string
|
||||
expectedFrom?: string
|
||||
}) {
|
||||
try {
|
||||
const res = await apiFetch('/api/dashboard/tasks/agent', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
title: data.title,
|
||||
detail: data.detail ?? null,
|
||||
source: data.source ?? 'iris',
|
||||
priority: data.priority ?? 'Medium',
|
||||
assignedTo: data.assignedTo ?? null,
|
||||
expectedFrom: data.expectedFrom ?? null,
|
||||
}),
|
||||
})
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
||||
await this.fetchBoard()
|
||||
await this.fetchAgentOverview()
|
||||
return await res.json() as DashboardTaskDto
|
||||
} catch (err) {
|
||||
console.warn('[TaskStore] createAgentTask failed', err)
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
/* ── Polling ──────────────────────────────────── */
|
||||
startPolling() {
|
||||
if (this.refreshInterval) return
|
||||
|
||||
Reference in New Issue
Block a user