import { useEffect, useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";
import { Crosshair, Power } from "lucide-react";
import NodeSphere from "../components/NodeSphere";
import Terminal from "../components/Terminal";
import { openWindow } from "../utils/navigation";
const engineStatusContent = {
idle: { title: "微信引擎未运行", description: "启动后等待并处理本地微信消息。" },
running: { title: "微信引擎运行中", description: "已处理 26 条消息 · 当前队列 0" },
error: { title: "微信引擎运行异常", description: "启动失败,请查看运行日志并检查本地配置。" },
};
const requiredAnnotationTypes = ["contact_list", "chat_content", "input_box", "unread_message"];
const initialChecks = [
{ id: "model", label: "大模型连接情况", detail: "配置完整,连接延迟 324ms", status: "waiting", passed: true },
{ id: "annotation", label: "微信区域标注情况", detail: "联系人、聊天内容、输入框和发送区域完整", status: "waiting", passed: true },
{ id: "window", label: "微信窗口连接情况", detail: "已找到 WeChat 主窗口", status: "waiting", passed: true },
];
function hasCompleteAnnotation(annotation) {
const regionTypes = new Set(annotation?.regions?.map((region) => region.type) || []);
return requiredAnnotationTypes.every((regionType) => regionTypes.has(regionType));
}
const wait = (duration) => new Promise((resolve) => setTimeout(resolve, duration));
export default function ClonePage() {
const [engineStatus, setEngineStatus] = useState("idle");
const [engineBusy, setEngineBusy] = useState(false);
const [annotationBusy, setAnnotationBusy] = useState(false);
const [annotationComplete, setAnnotationComplete] = useState(false);
const [agentLogs, setAgentLogs] = useState([{ level: "info", message: "[12:30:01] 等待启动" }]);
const [checkOpen, setCheckOpen] = useState(false);
const [checks, setChecks] = useState(initialChecks);
const [checkPhase, setCheckPhase] = useState("idle");
const [autoSendPaused, setAutoSendPaused] = useState(false);
const engineRunning = engineStatus === "running";
const statusContent = engineStatusContent[engineStatus];
useEffect(() => {
if (!window.__TAURI_INTERNALS__) return undefined;
let unlisten;
let cancelled = false;
listen("engine-state-changed", (event) => {
const running = event.payload?.enabled === true;
setEngineStatus(running ? "running" : "idle");
if (!running) setAutoSendPaused(false);
setEngineBusy(false);
}).then((cleanup) => { if (cancelled) cleanup(); else unlisten = cleanup; });
return () => { cancelled = true; if (unlisten) unlisten(); };
}, []);
useEffect(() => {
if (!window.__TAURI_INTERNALS__) return undefined;
let unlisten;
let cancelled = false;
async function observeAnnotationCompletion() {
const cleanup = await listen("annotation-completion-changed", (event) => setAnnotationComplete(event.payload === true));
if (cancelled) { cleanup(); return; }
unlisten = cleanup;
const annotation = await invoke("load_regions").catch(() => null);
if (!cancelled) setAnnotationComplete(hasCompleteAnnotation(annotation));
}
void observeAnnotationCompletion();
return () => { cancelled = true; if (unlisten) unlisten(); };
}, []);
async function toggleAgent() {
if (engineBusy) return false;
if (!window.__TAURI_INTERNALS__) {
setEngineStatus(engineRunning ? "idle" : "running");
setAutoSendPaused(false);
setAgentLogs((current) => [...current, { level: "info", message: engineRunning ? "[12:38:30] 引擎已停止" : "[12:38:21] 引擎启动成功" }]);
return true;
}
setEngineBusy(true);
try {
if (engineRunning) {
await invoke("stop_agent");
await invoke("stop_vision_stream");
setEngineStatus("idle");
setAutoSendPaused(false);
setAgentLogs((current) => [...current.slice(-300), { level: "warning", message: "引擎已停用,暂未读取 Rust 日志" }]);
} else {
await invoke("start_vision_stream");
try { await invoke("start_agent"); } catch (error) { await invoke("stop_vision_stream").catch(() => {}); throw new Error(`agent 启动失败:${String(error)}`); }
setEngineStatus("running");
setAutoSendPaused(false);
setAgentLogs((current) => [...current.slice(-300), { level: "info", message: "引擎已启动,暂未读取 Rust 日志" }]);
}
return true;
} catch (error) {
setEngineStatus("error");
setAgentLogs((current) => [...current, { level: "error", message: String(error) }]);
return false;
} finally {
setEngineBusy(false);
}
}
function toggleAutoSend() {
setAutoSendPaused((paused) => {
const nextPaused = !paused;
setAgentLogs((current) => [
...current.slice(-300),
{
level: nextPaused ? "warning" : "info",
message: nextPaused ? "已暂停自动发送" : "已恢复自动发送",
},
]);
return nextPaused;
});
}
function requestToggle() {
if (engineRunning) { void toggleAgent(); return; }
setChecks(initialChecks);
setCheckPhase("idle");
setCheckOpen(true);
setTimeout(runStartupChecks, 220);
}
async function runStartupChecks() {
setCheckPhase("checking");
setChecks(initialChecks);
for (let index = 0; index < initialChecks.length; index += 1) {
setChecks((items) => items.map((item, itemIndex) => ({ ...item, status: itemIndex === index ? "checking" : itemIndex < index ? "passed" : "waiting" })));
await wait(950);
const check = initialChecks[index];
if (!check.passed) {
setChecks((items) => items.map((item, itemIndex) => ({ ...item, status: itemIndex === index ? "failed" : item.status })));
setCheckPhase("failed");
await wait(1600);
setCheckOpen(false);
return;
}
setChecks((items) => items.map((item, itemIndex) => ({ ...item, status: itemIndex === index ? "passed" : item.status })));
}
setCheckPhase("starting");
const started = await toggleAgent();
if (started) { setCheckPhase("passed"); await wait(900); setCheckOpen(false); } else { setCheckPhase("failed-start"); await wait(1600); setCheckOpen(false); }
}
async function startAnnotation() {
if (annotationBusy) return;
if (!window.__TAURI_INTERNALS__) { setAgentLogs((current) => [...current.slice(-300), { level: "warning", message: "窗口选择标注请在 Tauri Windows 应用中使用" }]); return; }
setAnnotationBusy(true);
try { await invoke("enter_window_select_mode"); setAgentLogs((current) => [...current.slice(-300), { level: "info", message: "已进入窗口选择模式,请点击需要标注的窗口" }]); }
catch (error) { setAgentLogs((current) => [...current.slice(-300), { level: "error", message: String(error) }]); }
finally { setAnnotationBusy(false); }
}
return (
{statusContent.description}{statusContent.title}
正在检测引擎启动环境
全部检查成功,正在启动引擎...
: null} {phase === "failed" || phase === "failed-start" ?检查失败,启动流程已终止。
: null}