vault-os/dashboard/src/pages/AgentQueuePage.tsx
Harald Hoyer f820a72b04 Initial implementation of vault-os
Complete implementation across all 13 phases:

- vault-core: types, YAML frontmatter parsing, entity classification,
  filesystem ops, config, prompt composition, validation, search
- vault-watch: filesystem watcher with daemon write filtering, event
  classification
- vault-scheduler: cron engine, process executor, task runner with
  retry logic and concurrency limiting
- vault-api: Axum REST API (15 route modules), WebSocket with broadcast,
  AI assistant proxy, validation, templates
- Dashboard: React + TypeScript + Tailwind v4 with kanban, CodeMirror
  editor, dynamic view system, AI chat sidebar
- Nix flake with dev shell and NixOS module
- Graceful shutdown, inotify overflow recovery, tracing instrumentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:21:17 +01:00

70 lines
2.5 KiB
TypeScript

import { useAgentTasks } from '../hooks/useApi';
import { StatusBadge } from '../components/StatusBadge';
import type { AgentTask, AgentTaskStatus } from '../api/types';
const COLUMNS: { id: AgentTaskStatus; label: string }[] = [
{ id: 'queued', label: 'Queued' },
{ id: 'running', label: 'Running' },
{ id: 'done', label: 'Done' },
{ id: 'failed', label: 'Failed' },
];
export function AgentQueuePage() {
const { data: tasks, isLoading } = useAgentTasks();
const byStatus = (s: AgentTaskStatus) => (tasks || []).filter((t) => t.status === s);
return (
<div className="p-6">
<h1 className="mb-4 text-lg font-semibold">Agent Queue</h1>
{isLoading ? (
<div className="text-text-muted">Loading...</div>
) : (
<div className="flex gap-4">
{COLUMNS.map((col) => {
const items = byStatus(col.id);
return (
<div key={col.id} className="w-72 shrink-0">
<div className="mb-2 flex items-center justify-between px-1">
<h3 className="text-sm font-semibold text-text-secondary">{col.label}</h3>
<span className="text-xs text-text-muted">{items.length}</span>
</div>
<div className="space-y-2 rounded-lg border border-border bg-surface p-2">
{items.length === 0 ? (
<div className="py-4 text-center text-xs text-text-muted">Empty</div>
) : (
items.map((task) => <AgentTaskCard key={task.id} task={task} />)
)}
</div>
</div>
);
})}
</div>
)}
</div>
);
}
function AgentTaskCard({ task }: { task: AgentTask }) {
return (
<div className="rounded-lg border border-border bg-surface-raised p-3">
<div className="mb-1 text-sm font-medium text-text-primary">{task.title}</div>
<div className="flex items-center gap-2 text-xs text-text-secondary">
<span>{task.agent}</span>
<StatusBadge value={task.priority} />
{task.type && <span className="text-text-muted">{task.type}</span>}
</div>
{task.error && (
<div className="mt-2 truncate rounded bg-danger/10 px-2 py-1 text-xs text-danger">
{task.error}
</div>
)}
{task.started && (
<div className="mt-1 text-xs text-text-muted">
started: {new Date(task.started).toLocaleTimeString()}
</div>
)}
</div>
);
}