feat(backthink): 后台思考面板并入已存记录——不再只读WS实时事件
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

后台思考页此前只读 /ws/chat 的 backthink/thinking WS 实时事件(后台任务完成才有),DB里
270 条 backthink_records 看不到。新增 adminBackthink() 拉 GET /api/v1/admin/backthink +
useAutoReload(10s),与 WS 事件按 id 去重、按 at 倒序展示;空态/数据源说明更新。
验收: npm run build 99模块全绿
This commit is contained in:
Aska committed 2026-09-07 18:44:58 +08:00
1 parent db8465f68b
commit 0a645b7212
2 files changed
+24 -7

No files matched your search

+18 -7
View File
@@ -6,6 +6,9 @@ import { Button, EmptyState, Surface, Tag } from "../../components/primitives";
import type { BackthinkItem } from "../../lib/types";
import { Icon } from "../../components/Icon";
import { FlowGraphView } from "./FlowGraph";
import { adminBackthink } from "../../lib/api";
import { useAsyncData } from "../../lib/useAsyncData";
import { useAutoReload } from "../hooks";
function BackthinkRow({ item }: { item: BackthinkItem }): React.ReactNode {
const markPushed = useAppStore((s) => s.markBackthinkPushed);
@@ -54,12 +57,20 @@ export function BackthinkModule(): React.ReactNode {
const log = useAuditStore((s) => s.log);
const [filter, setFilter] = useState<"all" | "notify" | "silent">("all");
const [interveneHint, setInterveneHint] = useState(false);
const items = backthink.filter((b) => {
if (filter === "notify") return b.shouldNotify === true;
if (filter === "silent") return b.shouldNotify !== true;
return true;
});
// Persisted records (design/12 §4) + live WS backthink events, deduped by id,
// newest first. The panel previously only showed live WS events and hid history.
const rec = useAsyncData(() => adminBackthink(100), []);
useAutoReload(rec.reload, 10000);
const byId = new Map<string, BackthinkItem>();
for (const b of backthink) if (b.id) byId.set(b.id, b);
for (const b of rec.data ?? []) if (b.id) byId.set(b.id, b);
const items = Array.from(byId.values())
.sort((a, b) => (b.at ?? 0) - (a.at ?? 0))
.filter((b) => {
if (filter === "notify") return b.shouldNotify === true;
if (filter === "silent") return b.shouldNotify !== true;
return true;
});
return (
<div className="space-y-5">
@@ -99,7 +110,7 @@ export function BackthinkModule(): React.ReactNode {
</div>
)}
<Notice>数据源:/ws/chat 下行 backthink / thinking 与 graph_update 事件(实时)。干预为后端 M10+ 提供,当前为只读展示。</Notice>
<Notice>数据源:GET /api/v1/admin/backthink(已存记录,每 10s 刷新)+ /ws/chat 下行 backthink / thinking 与 graph_update 事件(实时)合并去重。干预为后端 M10+ 提供,当前为只读展示。</Notice>
</div>
);
}
+6
View File
@@ -14,6 +14,7 @@ import type {
ApiErrorShape,
ApiKeyIssueResult,
AuditRecord,
BackthinkItem,
AutomationCreateResult,
AutomationRunResult,
ChannelTestResult,
@@ -683,3 +684,8 @@ export function adminObservabilityAudit(limit?: number): Promise<AuditRecord[]>
function limitQuery(limit?: number): string {
return limit && limit > 0 ? `?limit=${limit}` : "";
}
/** GET /api/v1/admin/backthink — persisted background-think records (newest first). */
export function adminBackthink(limit?: number): Promise<BackthinkItem[]> {
return request<BackthinkItem[]>(`/admin/backthink${limitQuery(limit)}`);
}