Files
codex-app-server/cloud/console-react/src/hooks/useProjectTools.ts
T
host ebc5624893 console: React 生产级重写(左列表 + 中对话 + 右详情)
旧单页 console.html 换成 Vite + React + TypeScript 单文件构建产物
(309525 字节,sha 90345ec8…,重建字节一致),源码在
cloud/console-react/,改页面只改 src 再 npm run build:console,
产物不手改。布局:左侧列表(模块导航 + 任务列表)、中间标准对话
(实时链路时间线 + 继续会话聊天框,共用 Chat 组件)、右侧详情
(元数据、操作、评审、审批、协调子任务、子代理、线程)。
API 与后端语义未改,key 只存浏览器 localStorage。
6 个 console 标记单测随实现改名更新(意图不变:壳确实调了
这些接口、turn 信息仍在详情里、旧 goal 输入仍不存在);
P1 标记单测未动且通过。
2026-10-29 06:32:38 +08:00

58 lines
2.8 KiB
TypeScript

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<Automation[]>([]);
const [autoMsg, setAutoMsg] = useState("");
const [triage, setTriage] = useState<Triage | null>(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 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<Triage>(paths.projectTriage(id));
setTriage(d);
setTriageError("");
} catch (e: any) { setTriageError("分诊加载失败:" + e.message); }
}, [getProjectId]);
return { automations, autoMsg, triage, triageError, refreshAutomations, createAutomation, cancelAutomation, refreshTriage };
}