+
+ 选一个模板填入「{field}」
+
+
+ {templates === null ? (
+
加载中…
+ ) : templates.length === 0 ? (
+
(暂无模板,去模板库新建。)
+ ) : (
+
+ {templates.map((t) => (
+ -
+
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/apps/web/lib/api/schema.d.ts b/apps/web/lib/api/schema.d.ts
index c8b9ac0..59036bb 100644
--- a/apps/web/lib/api/schema.d.ts
+++ b/apps/web/lib/api/schema.d.ts
@@ -377,6 +377,50 @@ export interface paths {
patch?: never;
trace?: never;
};
+ "/templates": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ /**
+ * List Templates
+ * @description 列出当前用户(stub)的模板。
+ */
+ get: operations["list_templates_templates_get"];
+ put?: never;
+ /**
+ * Create Template
+ * @description 新建模板(201)。title/body 空 → FastAPI 422(schema `min_length=1`)。
+ */
+ post: operations["create_template_templates_post"];
+ delete?: never;
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
+ "/templates/{template_id}": {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ get?: never;
+ put?: never;
+ post?: never;
+ /**
+ * Delete Template
+ * @description 删除模板(204)。不存在 → 404 NOT_FOUND。
+ */
+ delete: operations["delete_template_templates__template_id__delete"];
+ options?: never;
+ head?: never;
+ patch?: never;
+ trace?: never;
+ };
"/projects/{project_id}/world/generate": {
parameters: {
query?: never;
@@ -1719,6 +1763,78 @@ export interface components {
*/
job_id: string;
};
+ /**
+ * TeardownIngestView
+ * @description 拆书入库产物(贴 ww_agents.BookTeardownResult;落 rules 表)。F1。
+ */
+ TeardownIngestView: {
+ /**
+ * Themes
+ * @description 核心主题/立意清单
+ */
+ themes?: string[];
+ /**
+ * Archetypes
+ * @description 人物原型/角色模板清单
+ */
+ archetypes?: string[];
+ /**
+ * Structure
+ * @description 叙事结构概述
+ * @default
+ */
+ structure: string;
+ /**
+ * Hooks
+ * @description 抓人钩子/爽点套路清单
+ */
+ hooks?: string[];
+ };
+ /**
+ * TemplateCreateRequest
+ * @description POST /templates:新建一条提示词模板。
+ */
+ TemplateCreateRequest: {
+ /**
+ * Title
+ * @description 模板标题(非空,纯空白 → 422)
+ */
+ title: string;
+ /**
+ * Body
+ * @description 模板正文(非空,一键填入生成器的 brief/text)
+ */
+ body: string;
+ /**
+ * Category
+ * @description 可选分类
+ */
+ category?: string | null;
+ /**
+ * Tool Key
+ * @description 可选关联生成器(NULL=通用)
+ */
+ tool_key?: string | null;
+ };
+ /**
+ * TemplateResponse
+ * @description 模板视图(列出/创建后回显;snake_case)。
+ */
+ TemplateResponse: {
+ /**
+ * Id
+ * Format: uuid
+ */
+ id: string;
+ /** Title */
+ title: string;
+ /** Body */
+ body: string;
+ /** Category */
+ category?: string | null;
+ /** Tool Key */
+ tool_key?: string | null;
+ };
/**
* TestConnectionRequest
* @description POST /test:最小探测请求。
@@ -1861,7 +1977,8 @@ export interface components {
*
* 仅声明了 `ingest` 的工具可用。按入库表取用对应字段:
* - world_entities(金手指/词条)→ `world_entities`(贴 WorldEntityCardView:type/name/rules);
- * - outline(细纲)→ `chapter_no` + `scenes`(贴 OutlineSceneIngestView)。
+ * - outline(细纲)→ `chapter_no` + `scenes`(贴 OutlineSceneIngestView);
+ * - rules(拆书)→ `teardown`(贴 TeardownIngestView:themes/archetypes/structure/hooks)。
* `acknowledge_conflicts`:作者已查看并接受 continuity 预检冲突时置 true 放行(仿 accept gate)。
*/
ToolIngestRequest: {
@@ -1880,6 +1997,8 @@ export interface components {
* @description outline 入库的场景行(细纲)
*/
scenes?: components["schemas"]["OutlineSceneIngestView"][];
+ /** @description rules 入库的拆书结论(F1;拍平为可读规则条目) */
+ teardown?: components["schemas"]["TeardownIngestView"] | null;
/**
* Acknowledge Conflicts
* @description 作者已知悉并接受 continuity 冲突 → 放行入库
@@ -2866,6 +2985,88 @@ export interface operations {
};
};
};
+ list_templates_templates_get: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 200: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TemplateResponse"][];
+ };
+ };
+ };
+ };
+ create_template_templates_post: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path?: never;
+ cookie?: never;
+ };
+ requestBody: {
+ content: {
+ "application/json": components["schemas"]["TemplateCreateRequest"];
+ };
+ };
+ responses: {
+ /** @description Successful Response */
+ 201: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["TemplateResponse"];
+ };
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
+ delete_template_templates__template_id__delete: {
+ parameters: {
+ query?: never;
+ header?: never;
+ path: {
+ template_id: string;
+ };
+ cookie?: never;
+ };
+ requestBody?: never;
+ responses: {
+ /** @description Successful Response */
+ 204: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content?: never;
+ };
+ /** @description Validation Error */
+ 422: {
+ headers: {
+ [name: string]: unknown;
+ };
+ content: {
+ "application/json": components["schemas"]["HTTPValidationError"];
+ };
+ };
+ };
+ };
generate_world_projects__project_id__world_generate_post: {
parameters: {
query?: never;
diff --git a/apps/web/lib/api/server.ts b/apps/web/lib/api/server.ts
index 9494139..c135e8b 100644
--- a/apps/web/lib/api/server.ts
+++ b/apps/web/lib/api/server.ts
@@ -13,6 +13,7 @@ import type {
RuleListResponse,
SkillListResponse,
StyleFingerprintResponse,
+ TemplateResponse,
ToolboxListResponse,
WorldEntityListResponse,
} from "./types";
@@ -149,6 +150,16 @@ export async function fetchOutline(
}
}
+// 提示词/模板库列表(GET /templates,全局只读;裸数组)。
+// 任何错误(含后端未上线)降级为空列表,模板页照常渲染(进页不阻塞)。
+export async function fetchTemplates(): Promise