import { useCallback, useState } from "react"; import { api } from "../api/client"; import { paths } from "../api/paths"; import type { Automation, Triage } from "../api/types"; // Project-scoped tools shown in the centre for their own views: // automations (create/list/cancel) and the triage inbox (4 groups). export function useProjectTools(getProjectId: () => string) { const [automations, setAutomations] = useState([]); const [autoMsg, setAutoMsg] = useState(""); const [triage, setTriage] = useState(null); const [triageError, setTriageError] = useState(""); const refreshAutomations = useCallback(async (pid?: string) => { const id = pid !== undefined ? pid : getProjectId(); if (!id) { setAutomations([]); return; } try { const d = await api<{ automations: Automation[] }>(paths.projectAutomations(id)); setAutomations(d.automations || []); } catch (e: any) { setAutoMsg("自动化加载失败:" + e.message); } }, [getProjectId]); const createAutomation = useCallback(async (name: string, prompt: string, interval: string, repo: string) => { const pid = getProjectId(); if (!pid) { setAutoMsg("先选项目"); return; } if (!name.trim()) { setAutoMsg("自动化名称必填"); return; } if (!prompt.trim()) { setAutoMsg("定时任务内容必填"); return; } const body: { name: string; prompt: string; interval_seconds?: number; repo_url?: string } = { name: name.trim(), prompt: prompt.trim() }; if (interval.trim()) body.interval_seconds = parseInt(interval.trim(), 10); if (repo.trim()) body.repo_url = repo.trim(); try { await api(paths.projectAutomations(pid), "POST", body); setAutoMsg("自动化已创建(登记定义,到期后由执行器认领)"); await refreshAutomations(pid); } catch (e: any) { setAutoMsg("创建失败:" + e.message); } }, [getProjectId, refreshAutomations]); const updateAutomation = useCallback(async (a: Automation, name: string, prompt: string, interval: string, repo: string) => { const pid = getProjectId(); if (!pid) { setAutoMsg("先选项目"); return false; } const n = name.trim(); const p = prompt.trim(); if (!n) { setAutoMsg("自动化名称必填"); return false; } if (!p) { setAutoMsg("定时任务内容必填"); return false; } const body: { name?: string; prompt?: string; interval_seconds?: number; repo_url?: string | null } = {}; if (n !== (a.name || "")) body.name = n; if (p !== (a.prompt || "")) body.prompt = p; if (interval.trim()) { const v = parseInt(interval.trim(), 10); if (Number.isNaN(v)) { setAutoMsg("间隔秒数必须是数字"); return false; } if (v < 60) { setAutoMsg("间隔秒数最小 60"); return false; } if (v !== a.interval_seconds) body.interval_seconds = v; } const r = repo.trim(); if (r !== (a.repo_url || "")) body.repo_url = r === "" ? null : r; if (Object.keys(body).length === 0) { setAutoMsg("没有改动"); return false; } try { await api(paths.projectAutomation(pid, a.id), "PATCH", body); setAutoMsg("自动化已更新"); await refreshAutomations(pid); return true; } catch (e: any) { setAutoMsg("更新失败:" + e.message); return false; } }, [getProjectId, refreshAutomations]); const cancelAutomation = useCallback((id: string) => { const pid = getProjectId(); if (!pid) return; void api(paths.projectAutomationCancel(pid, id), "POST", {}) .then(() => { setAutoMsg("自动化已取消"); void refreshAutomations(pid); }) .catch((e: any) => setAutoMsg("取消失败:" + e.message)); }, [getProjectId, refreshAutomations]); const refreshTriage = useCallback(async (pid?: string) => { const id = pid !== undefined ? pid : getProjectId(); if (!id) { setTriage(null); return; } try { const d = await api(paths.projectTriage(id)); setTriage(d); setTriageError(""); } catch (e: any) { setTriageError("分诊加载失败:" + e.message); } }, [getProjectId]); return { automations, autoMsg, triage, triageError, refreshAutomations, createAutomation, updateAutomation, cancelAutomation, refreshTriage }; }