auto-sync: 2026-05-17 11:21:49
This commit is contained in:
@@ -1,84 +0,0 @@
|
||||
// 自定义 hooks
|
||||
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import * as api from '../api';
|
||||
import type { Task, Project, DaemonStatus } from '../types';
|
||||
|
||||
export function useProjects() {
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await api.listProjects();
|
||||
setProjects(data);
|
||||
setError(null);
|
||||
} catch (e) {
|
||||
setError(String(e));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => { refresh(); }, [refresh]);
|
||||
return { projects, loading, error, refresh };
|
||||
}
|
||||
|
||||
export function useTasks(projectId: string | null) {
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
if (!projectId) return;
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await api.listTasks(projectId);
|
||||
setTasks(data);
|
||||
setError(null);
|
||||
} catch (e) {
|
||||
setError(String(e));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [projectId]);
|
||||
|
||||
useEffect(() => { refresh(); }, [refresh]);
|
||||
return { tasks, loading, error, refresh };
|
||||
}
|
||||
|
||||
export function useDaemonStatus() {
|
||||
const [status, setStatus] = useState<DaemonStatus | null>(null);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
try {
|
||||
const data = await api.getDaemonStatus();
|
||||
setStatus(data);
|
||||
} catch {
|
||||
// Daemon may not be running
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
refresh();
|
||||
const interval = setInterval(refresh, 10000);
|
||||
return () => clearInterval(interval);
|
||||
}, [refresh]);
|
||||
|
||||
return { status, refresh };
|
||||
}
|
||||
|
||||
export function useSSE(onEvent: (data: unknown) => void) {
|
||||
const esRef = useRef<EventSource | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
esRef.current = api.createEventSource(onEvent, () => {
|
||||
// Auto-reconnect is handled by EventSource
|
||||
});
|
||||
return () => {
|
||||
esRef.current?.close();
|
||||
};
|
||||
}, [onEvent]);
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
// API 类型定义
|
||||
|
||||
export interface Task {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
status: string;
|
||||
assignee: string | null;
|
||||
assigned_by: string;
|
||||
depends_on: string | null;
|
||||
priority: number;
|
||||
task_type: string | null;
|
||||
risk_level: string | null;
|
||||
must_haves: string | null;
|
||||
output_path: string | null;
|
||||
result_summary: string | null;
|
||||
retry_count: number;
|
||||
max_retries: number;
|
||||
created_at: string | null;
|
||||
updated_at: string | null;
|
||||
completed_at: string | null;
|
||||
}
|
||||
|
||||
export interface Project {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
status: string;
|
||||
config: string | null;
|
||||
created_at: string | null;
|
||||
updated_at: string | null;
|
||||
}
|
||||
|
||||
export interface Observation {
|
||||
id: number;
|
||||
task_id: string | null;
|
||||
observer: string;
|
||||
severity: string;
|
||||
body: string;
|
||||
resolved_by: string | null;
|
||||
created_at: string | null;
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
id: number | null;
|
||||
task_id: string | null;
|
||||
agent: string | null;
|
||||
event_type: string;
|
||||
detail: string | null;
|
||||
created_at: string | null;
|
||||
}
|
||||
|
||||
export interface DaemonStatus {
|
||||
status: string;
|
||||
tick_count: number;
|
||||
uptime_seconds: number;
|
||||
active_projects: number;
|
||||
last_tick: string | null;
|
||||
}
|
||||
|
||||
export interface ReviewResult {
|
||||
verdict: string;
|
||||
score: number;
|
||||
gate: string;
|
||||
needs_human: boolean;
|
||||
results: ReviewStepResult[];
|
||||
}
|
||||
|
||||
export interface ReviewStepResult {
|
||||
step: string;
|
||||
verdict: string;
|
||||
score: number;
|
||||
details: string;
|
||||
suggestions: string[];
|
||||
}
|
||||
|
||||
export type SSEEventData = {
|
||||
event_type: string;
|
||||
task_id?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
Reference in New Issue
Block a user