返回 DeepSeek-Reasonix
ToolRecoveryPanel.tsx
根目录 / desktop / frontend / src / components / ToolRecoveryPanel.tsx
1 import { useEffect, useRef, useState } from "react";
2 import { app } from "../lib/bridge";
3 import { useT } from "../lib/i18n";
4 import type { ToolRecoveryBindings, ToolRecoverySnapshot } from "../lib/toolRecovery";
5 import "./ToolRecoveryPanel.css";
6
7 export function ToolRecoveryPanel({ tabId, sessionKey, running, refreshKey, bindings = app }: {
8 tabId: string; sessionKey: string; running: boolean; refreshKey: number;
9 bindings?: ToolRecoveryBindings;
10 }) {
11 const t = useT();
12 const generation = useRef(0);
13 const [snapshot, setSnapshot] = useState<ToolRecoverySnapshot | null>(null);
14 const [error, setError] = useState("");
15 useEffect(() => {
16 const own = ++generation.current;
17 setSnapshot(null); setError("");
18 if (!running && bindings.GetToolRecoveryForTab) {
19 void bindings.GetToolRecoveryForTab(tabId).then(next => {
20 if (generation.current === own) setSnapshot(next);
21 }).catch(err => { if (generation.current === own) setError(String(err)); });
22 }
23 return () => { generation.current++; };
24 }, [bindings, tabId, sessionKey, running, refreshKey]);
25
26 if (!snapshot?.calls.length && !error) return null;
27 return <section className="notice-line notice-line--warn tool-recovery-panel" aria-label={t("toolRecovery.title")}>
28 <details open>
29 <summary className="notice-line__title">{t("toolRecovery.title")}</summary>
30 <div className="notice-line__text">
31 {error && <p role="alert">{error}</p>}
32 {!!snapshot?.calls.length && <p>{t("toolRecovery.retired")}</p>}
33 {(snapshot?.calls ?? []).map(call => <div key={call.identity.attempt_id}>
34 <p>{call.identity.canonical_tool} · {t("toolRecovery.unknown")}</p>
35 <details><summary>{t("toolRecovery.details")}</summary>
36 <p>{call.identity.resource_scope}</p>
37 <p>{call.identity.argument_digest}</p>
38 {call.arguments !== undefined && <pre>{JSON.stringify(call.arguments, null, 2)}</pre>}
39 </details>
40 </div>)}
41 </div>
42 </details>
43 </section>;
44 }
45
45 lines Plain Text