Phase 1(写作工作台重构):编辑器「工具箱」按钮打开内联面板,不离开写作界面即可调用 全部生成器(含金手指——后端 golden-finger 早已齐全,此处首次露出)。复用 GeneratorRunner, 为其加可选 onInsertText:文本类产物(开篇/简介/续写/扩写等)点「插入正文」直接追加到章末, 可入库类仍走既有 ingest。useToolboxTools 客户端拉描述符(已单测)。润色/续写/工具箱三卡互斥。
49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect, useState } from "react";
|
||
|
||
import { api } from "@/lib/api/client";
|
||
import { useToast } from "@/components/Toast";
|
||
import type { ToolDescriptorView } from "@/lib/api/types";
|
||
|
||
// 客户端拉取创作工具箱全量描述符(GET /skills/toolbox),供编辑器内联工具箱调用。
|
||
// 描述符只读、少变,进面板时拉一次即可。
|
||
export type ToolboxStatus = "loading" | "ready" | "error";
|
||
|
||
export interface UseToolboxTools {
|
||
status: ToolboxStatus;
|
||
tools: ToolDescriptorView[];
|
||
}
|
||
|
||
export function useToolboxTools(): UseToolboxTools {
|
||
const [status, setStatus] = useState<ToolboxStatus>("loading");
|
||
const [tools, setTools] = useState<ToolDescriptorView[]>([]);
|
||
const toast = useToast();
|
||
|
||
useEffect(() => {
|
||
let cancelled = false;
|
||
void (async (): Promise<void> => {
|
||
try {
|
||
const { data, error } = await api.GET("/skills/toolbox", {});
|
||
if (cancelled) return;
|
||
if (error || !data) {
|
||
setStatus("error");
|
||
toast("工具箱加载失败,请重试。", "error");
|
||
return;
|
||
}
|
||
setTools(data.tools ?? []);
|
||
setStatus("ready");
|
||
} catch {
|
||
if (cancelled) return;
|
||
setStatus("error");
|
||
toast("工具箱加载异常,请检查网络。", "error");
|
||
}
|
||
})();
|
||
return () => {
|
||
cancelled = true;
|
||
};
|
||
}, [toast]);
|
||
|
||
return { status, tools };
|
||
}
|