diff --git a/src/lib/initDB.ts b/src/lib/initDB.ts index a210b74..7af36b9 100644 --- a/src/lib/initDB.ts +++ b/src/lib/initDB.ts @@ -79,7 +79,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => modelName: "", vendorId: null, key: "scriptAgent", - name: "剧本AI", + name: "剧本Agent", desc: "用于读取原文生成故事骨架、改编策略,建议使用具备强大文本理解和生成能力的模型", disabled: false, }, @@ -88,7 +88,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => modelName: "", vendorId: null, key: "productionAgent", - name: "生产AI", + name: "生产Agent", desc: "对工作流进行调度和管理,建议使用具备较强的逻辑推理和任务管理能力的模型", disabled: false, }, @@ -96,7 +96,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => model: "", modelName: "", vendorId: null, - key: "universalAgent", + key: "universalAi", name: "通用AI", desc: "用于小说事件提取、资产提示词生成、台词提取等边缘功能,建议使用具备较强文本处理能力的模型", disabled: false, @@ -436,368 +436,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.unique(["scriptId", "assetId"]); }, }, - { - name: "o_skillList", - builder: (table) => { - table.text("id").notNullable(); - table.text("md5").notNullable(); - table.text("path").notNullable(); - table.text("name").notNullable(); //文件名 - table.text("description").notNullable(); //描述 - table.text("embedding"); // 向量嵌入 JSON - table.text("type").notNullable(); // "main" | "references" - table.integer("createTime").notNullable(); - table.integer("updateTime").notNullable(); - table.integer("state").notNullable(); // 1正常,0正在生成description,-1description为空。-2归属为空,-3md5变动,-4文件不存在 - table.primary(["id"]); - }, - initData: async (knex) => { - const list = [ - { - id: "4fb36012e56e395b425569987f5dab0e", - md5: "fca3c269c5f325a65dafa663c9bb9773", - path: "production_agent_decision.md", - name: "production_agent_decision", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "017b6338d7aa227cd614ec1fb25fd83e", - md5: "2610b80abe4bd048fe61c73adc7388ac", - path: "production_agent_execution.md", - name: "production_agent_execution", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "f03c8e67b61580de9ea5b9d166521b67", - md5: "d41d8cd98f00b204e9800998ecf8427e", - path: "production_agent_supervision.md", - name: "production_agent_supervision", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "50b49d8af5d364665b463c23f6a4d8bb", - md5: "fbba66e0df2426996277b299710c3033", - path: "script_agent_decision.md", - name: "script_agent_decision", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "427727727e1095c54b6840cd21382d82", - md5: "7e5911242af7233854d533278c6a8ccb", - path: "script_agent_execution.md", - name: "script_agent_execution", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "02848fb0dd582fd926502c77ecf9679c", - md5: "7a8b6a311b015cd47bf17cc52b935348", - path: "script_agent_supervision.md", - name: "script_agent_supervision", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "a1e818cc03a0b355b239ac1fb0512969", - md5: "1fd22029e8047aa30b0dfd703cb837ed", - path: "universal_agent.md", - name: "universal_agent", - description: "", - embedding: "", - type: "main", - createTime: 1774447310118, - updateTime: 1774447310118, - state: -1, - }, - { - id: "3e5efec258c8d8e6a39bcef12f8ee058", - md5: "efccb0464cfd472861b49ebf737d4820", - path: "references/event_extract.md", - name: "event_extract", - description: - "专为小说改编短剧设计的文本分析助手,逐章提取涉及角色、核心事件、主线关系、信息密度、预估集长及情绪强度等结构化信息,以Markdown表格形式输出,并附汇总统计,辅助短剧制作的内容规划与时长估算。", - embedding: "", - type: "references", - createTime: 1774447310118, - updateTime: 1774450165911, - state: 1, - }, - { - id: "52c51fa8655f899a1b7aae9b6aad7251", - md5: "783678aaab829b34e7c30a414c356bf6", - path: "references/novel_character_extract.md", - name: "novel_character_extract", - description: - "专为小说内容分析设计的角色提取助手,从原文中识别并结构化输出所有重要角色的视觉描述信息,包括外貌、服饰、体态、状态变体等字段,供美术制作和AI角色图生成使用。", - embedding: "", - type: "references", - createTime: 1774447310118, - updateTime: 1774450080903, - state: 1, - }, - { - id: "6d46cdca10b2f49e07e515885d1387a0", - md5: "10544d12c4ef011e6b3b63a99b8c7fa8", - path: "references/novel_props_extract.md", - name: "novel_props_extract", - description: - "专注于从小说原文中提取道具物品信息的分析助手,能识别武器、法器、药物等各类道具,生成包含外观、材质、尺寸、功能及状态变体的结构化视觉描述表格,供美术制作和AI绘图使用。", - embedding: "", - type: "references", - createTime: 1774447310118, - updateTime: 1774450094771, - state: 1, - }, - { - id: "1864df75d1d65f76e275046649ecaef8", - md5: "65603aa495a541f54c55b7f30e149f45", - path: "references/novel_scene_extract.md", - name: "novel_scene_extract", - description: - "专注于从小说原文中提取并结构化场景信息的分析助手,可识别各类场景地点,输出包含空间描述、光照氛围、关键陈设、色调基调等字段的标准化场景资产表,用于美术制作和AI绘图的场景概念图生成。", - embedding: "", - type: "references", - createTime: 1774447310118, - updateTime: 1774450161878, - state: 1, - }, - { - id: "7fbce6f90d7d85496ba9817e9622e640", - md5: "830559e8f2cd5d0fa8e6df48a164fe2d", - path: "references/video_dialogue_extract.md", - name: "video_dialogue_extract", - description: - "这是一个专门从视频分镜提示词中提取结构化台词、旁白与音效信息的AI助手配置文档,定义了完整的输出格式(含镜号、角色、台词类型、表演指导等字段)、提取规则及处理流程,用于将视频分镜描述转化为标准化台词表。", - embedding: "", - type: "references", - createTime: 1774447310118, - updateTime: 1774450180712, - state: 1, - }, - { - id: "31fb5c5a1f514ec1e66b4eba9f22d4db", - md5: "43e63450efe0c9af8a3a40b036d36cb4", - path: "references/pipeline.md", - name: "pipeline", - description: - "面向短剧改编项目的四阶段流水线说明文档,涵盖事件提取、故事骨架、改编策略、剧本编写的串行执行流程,定义了决策层、执行层、监督层的协作规范及派发、审核、修复的交互格式与质量门控标准。", - embedding: "", - type: "references", - createTime: 1774451946248, - updateTime: 1774451984533, - state: 1, - }, - { - id: "27dc2dfc901de2180227d0269217583a", - md5: "7d353be4bab7a794436d9abff2b9c6ee", - path: "references/adaptation_format.md", - name: "adaptation_format", - description: - "本文档规定了改编策略输出的标准格式,包括核心改编原则、删除决策和世界观呈现策略三大模块的书写规范,明确各模块所需涵盖的维度与要素,用于指导竖屏短剧等载体的文学改编工作。", - embedding: "", - type: "references", - createTime: 1774452010535, - updateTime: 1774452022083, - state: 1, - }, - { - id: "d49fa09504fe784a8e6eb102756c6d56", - md5: "2ef08a7479f29d74986999ceb02092c8", - path: "references/event_format.md", - name: "event_format", - description: - "本文档规定了影视改编项目中事件表的标准输出格式,包括文件头、事件表格、各字段填写规范(章节、角色、核心事件、主线关系、情绪强度、预估时长)及汇总统计模板,用于指导从原著提取事件并评估改编集数与压缩比的第一阶段工作。", - embedding: "", - type: "references", - createTime: 1774452010535, - updateTime: 1774452030858, - state: 1, - }, - { - id: "797906c2ddf0750f050bcdeae23eae3d", - md5: "f5e7fe6db7e05db69d5dc327c4c538f2", - path: "references/script_format.md", - name: "script_format", - description: - "本文档为竖屏短剧剧本的输出格式规范,定义了文件头、节拍结构、分镜脚本、画面描述、台词、转场标注等标准格式要求,并附有时长控制参数与自查清单,供AI视频生成和导演制作使用。", - embedding: "", - type: "references", - createTime: 1774452010535, - updateTime: 1774452042934, - state: 1, - }, - { - id: "1abd8675c0c3e62b20c0b151d2ec0fb1", - md5: "a587532c737ce15022e1522021f099bb", - path: "references/skeleton_format.md", - name: "skeleton_format", - description: - "本文档定义了故事骨架文件(skeleton.md)的标准化输出格式,涵盖故事核、人物成长隐线、三幕结构、分集决策模板、全局删减记录、付费卡点设计及自查清单,用于指导编剧将章节事件列表转化为结构完整的剧集改编方案。", - embedding: "", - type: "references", - createTime: 1774452010535, - updateTime: 1774452057184, - state: 1, - }, - { - id: "0b7828d7a6ab458a4b201122f08d6c16", - md5: "120b3c856f1b2a8a429e11319e8c95fe", - path: "references/quality_criteria.md", - name: "quality_criteria", - description: - "本文档为影视/短剧项目的质量审核标准手册,涵盖事件表、故事骨架、改编策略和剧本四大模块的详细审核规则,规定了格式规范、角色名称统一、时长合理性、画面可执行性及场景氛围一致性等审核要求,用于确保各阶段产出物的内容准确性与制作可行性。", - embedding: "", - type: "references", - createTime: 1774452068093, - updateTime: 1774452087877, - state: 1, - }, - { - id: "5c1772b5f9c420d9eae9ca02914ba087", - md5: "c710ab7d237e1f0c5aa3d208e0f5b484", - path: "references/plan.md", - name: "plan", - description: - "该文档定义了AI代理生成执行计划的规范,包括任务总览、步骤列表(含编号、名称、详细内容、预期输出及依赖关系)和执行顺序标注,并提供标准回复模板,用于将用户需求拆解为可直接传入子代理工具执行的具体步骤。", - embedding: "", - type: "references", - createTime: 1774452098447, - updateTime: 1774452109574, - state: 1, - }, - { - id: "75a45cf996015ca819582873887ec301", - md5: "6045d76873fd58b8b87a914a21a38439", - path: "references/derive_assets_extraction.md", - name: "derive_assets_extraction", - description: - "本文档是一份技术操作指南,说明如何根据剧本内容和已有资产列表,提取每个资产在剧情中出现的不同视觉状态变体(derive),并通过工具函数读取和写入数据,用于后续图片生成参考。", - embedding: "", - type: "references", - createTime: 1774452119499, - updateTime: 1774452129516, - state: 1, - }, - { - id: "fce75f69d704c19bebcb356bc1bd6e81", - md5: "a3b3432854970f22949ba47236a6532f", - path: "references/storyboard_generation.md", - name: "storyboard_generation", - description: - "根据剧本和资产列表生成结构化分镜面板的工具指南,涵盖分镜拆分原则、字段填写规范及工具调用流程,用于将剧本转化为含画面描述、镜头语言、台词和AI绘图提示词的分镜数据。", - embedding: "", - type: "references", - createTime: 1774452119499, - updateTime: 1774452140873, - state: 1, - }, - ]; - await Promise.all( - list.map(async (item) => { - const embedding = await getEmbedding(item.description); - item.embedding = JSON.stringify(embedding); - }), - ); - await knex("o_skillList").insert(list); - }, - }, - { - name: "o_skillAttribution", - builder: (table) => { - table.text("skillId").notNullable().references("id").inTable("o_skillList").onDelete("CASCADE"); - table.text("attribution").notNullable(); // "production_agent_decision.md" | "production_agent_execution.md" | "production_agent_supervision.md" | "script_agent_decision.md" | "script_agent_execution.md" | "script_agent_supervision.md" | "universal_agent.md" - table.primary(["skillId", "attribution"]); - table.index(["attribution"]); - }, - initData: async (knex) => { - await knex("o_skillAttribution").insert([ - { - skillId: "52c51fa8655f899a1b7aae9b6aad7251", - attribution: "universal_agent.md", - }, - { - skillId: "6d46cdca10b2f49e07e515885d1387a0", - attribution: "universal_agent.md", - }, - { - skillId: "1864df75d1d65f76e275046649ecaef8", - attribution: "universal_agent.md", - }, - { - skillId: "3e5efec258c8d8e6a39bcef12f8ee058", - attribution: "universal_agent.md", - }, - { - skillId: "7fbce6f90d7d85496ba9817e9622e640", - attribution: "universal_agent.md", - }, - { - skillId: "31fb5c5a1f514ec1e66b4eba9f22d4db", - attribution: "script_agent_decision.md", - }, - { - skillId: "27dc2dfc901de2180227d0269217583a", - attribution: "script_agent_execution.md", - }, - { - skillId: "d49fa09504fe784a8e6eb102756c6d56", - attribution: "script_agent_execution.md", - }, - { - skillId: "797906c2ddf0750f050bcdeae23eae3d", - attribution: "script_agent_execution.md", - }, - { - skillId: "1abd8675c0c3e62b20c0b151d2ec0fb1", - attribution: "script_agent_execution.md", - }, - { - skillId: "0b7828d7a6ab458a4b201122f08d6c16", - attribution: "script_agent_supervision.md", - }, - { - skillId: "5c1772b5f9c420d9eae9ca02914ba087", - attribution: "production_agent_decision.md", - }, - { - skillId: "75a45cf996015ca819582873887ec301", - attribution: "production_agent_execution.md", - }, - { - skillId: "fce75f69d704c19bebcb356bc1bd6e81", - attribution: "production_agent_execution.md", - }, - ]); - }, - }, //记忆表(message=原始消息, summary=压缩摘要) { name: "memories", diff --git a/src/router.ts b/src/router.ts index 72cf4c1..fa41817 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,4 +1,4 @@ -// @routes-hash 58fd64b8de7872e80874b1244bbe3569 +// @routes-hash 771456dc4b3772798bc855d6d2f8463e import { Express } from "express"; import route1 from "./routes/agents/clearMemory"; @@ -94,24 +94,25 @@ import route90 from "./routes/setting/memoryConfig/getMemory"; import route91 from "./routes/setting/memoryConfig/sureMemory"; import route92 from "./routes/setting/promptManage/getPrompt"; import route93 from "./routes/setting/promptManage/updatePrompt"; -import route94 from "./routes/setting/skillManagement/addSkill"; -import route95 from "./routes/setting/skillManagement/deleteSkill"; -import route96 from "./routes/setting/skillManagement/embeddingSkill"; -import route97 from "./routes/setting/skillManagement/generateDescription"; -import route98 from "./routes/setting/skillManagement/getSkillList"; -import route99 from "./routes/setting/skillManagement/scanSkills"; -import route100 from "./routes/setting/skillManagement/updateSkill"; -import route101 from "./routes/setting/vendorConfig/addVendor"; -import route102 from "./routes/setting/vendorConfig/deleteVendor"; -import route103 from "./routes/setting/vendorConfig/getVendorList"; -import route104 from "./routes/setting/vendorConfig/modelTest"; -import route105 from "./routes/setting/vendorConfig/updateCode"; -import route106 from "./routes/setting/vendorConfig/updateVendor"; -import route107 from "./routes/task/getProject"; -import route108 from "./routes/task/getTaskApi"; -import route109 from "./routes/task/getTaskCategories"; -import route110 from "./routes/task/taskDetails"; -import route111 from "./routes/test/test"; +import route94 from "./routes/setting/skillManagement/backup/addSkill"; +import route95 from "./routes/setting/skillManagement/backup/deleteSkill"; +import route96 from "./routes/setting/skillManagement/backup/embeddingSkill"; +import route97 from "./routes/setting/skillManagement/backup/generateDescription"; +import route98 from "./routes/setting/skillManagement/backup/getSkillList"; +import route99 from "./routes/setting/skillManagement/backup/scanSkills"; +import route100 from "./routes/setting/skillManagement/backup/updateSkill"; +import route101 from "./routes/setting/skillManagement/getSkillList"; +import route102 from "./routes/setting/vendorConfig/addVendor"; +import route103 from "./routes/setting/vendorConfig/deleteVendor"; +import route104 from "./routes/setting/vendorConfig/getVendorList"; +import route105 from "./routes/setting/vendorConfig/modelTest"; +import route106 from "./routes/setting/vendorConfig/updateCode"; +import route107 from "./routes/setting/vendorConfig/updateVendor"; +import route108 from "./routes/task/getProject"; +import route109 from "./routes/task/getTaskApi"; +import route110 from "./routes/task/getTaskCategories"; +import route111 from "./routes/task/taskDetails"; +import route112 from "./routes/test/test"; export default async (app: Express) => { app.use("/api/agents/clearMemory", route1); @@ -207,22 +208,23 @@ export default async (app: Express) => { app.use("/api/setting/memoryConfig/sureMemory", route91); app.use("/api/setting/promptManage/getPrompt", route92); app.use("/api/setting/promptManage/updatePrompt", route93); - app.use("/api/setting/skillManagement/addSkill", route94); - app.use("/api/setting/skillManagement/deleteSkill", route95); - app.use("/api/setting/skillManagement/embeddingSkill", route96); - app.use("/api/setting/skillManagement/generateDescription", route97); - app.use("/api/setting/skillManagement/getSkillList", route98); - app.use("/api/setting/skillManagement/scanSkills", route99); - app.use("/api/setting/skillManagement/updateSkill", route100); - app.use("/api/setting/vendorConfig/addVendor", route101); - app.use("/api/setting/vendorConfig/deleteVendor", route102); - app.use("/api/setting/vendorConfig/getVendorList", route103); - app.use("/api/setting/vendorConfig/modelTest", route104); - app.use("/api/setting/vendorConfig/updateCode", route105); - app.use("/api/setting/vendorConfig/updateVendor", route106); - app.use("/api/task/getProject", route107); - app.use("/api/task/getTaskApi", route108); - app.use("/api/task/getTaskCategories", route109); - app.use("/api/task/taskDetails", route110); - app.use("/api/test/test", route111); + app.use("/api/setting/skillManagement/backup/addSkill", route94); + app.use("/api/setting/skillManagement/backup/deleteSkill", route95); + app.use("/api/setting/skillManagement/backup/embeddingSkill", route96); + app.use("/api/setting/skillManagement/backup/generateDescription", route97); + app.use("/api/setting/skillManagement/backup/getSkillList", route98); + app.use("/api/setting/skillManagement/backup/scanSkills", route99); + app.use("/api/setting/skillManagement/backup/updateSkill", route100); + app.use("/api/setting/skillManagement/getSkillList", route101); + app.use("/api/setting/vendorConfig/addVendor", route102); + app.use("/api/setting/vendorConfig/deleteVendor", route103); + app.use("/api/setting/vendorConfig/getVendorList", route104); + app.use("/api/setting/vendorConfig/modelTest", route105); + app.use("/api/setting/vendorConfig/updateCode", route106); + app.use("/api/setting/vendorConfig/updateVendor", route107); + app.use("/api/task/getProject", route108); + app.use("/api/task/getTaskApi", route109); + app.use("/api/task/getTaskCategories", route110); + app.use("/api/task/taskDetails", route111); + app.use("/api/test/test", route112); } diff --git a/src/routes/setting/skillManagement/addSkill.ts b/src/routes/setting/skillManagement/backup/addSkill.ts similarity index 100% rename from src/routes/setting/skillManagement/addSkill.ts rename to src/routes/setting/skillManagement/backup/addSkill.ts diff --git a/src/routes/setting/skillManagement/deleteSkill.ts b/src/routes/setting/skillManagement/backup/deleteSkill.ts similarity index 100% rename from src/routes/setting/skillManagement/deleteSkill.ts rename to src/routes/setting/skillManagement/backup/deleteSkill.ts diff --git a/src/routes/setting/skillManagement/embeddingSkill.ts b/src/routes/setting/skillManagement/backup/embeddingSkill.ts similarity index 100% rename from src/routes/setting/skillManagement/embeddingSkill.ts rename to src/routes/setting/skillManagement/backup/embeddingSkill.ts diff --git a/src/routes/setting/skillManagement/generateDescription.ts b/src/routes/setting/skillManagement/backup/generateDescription.ts similarity index 95% rename from src/routes/setting/skillManagement/generateDescription.ts rename to src/routes/setting/skillManagement/backup/generateDescription.ts index 98ac70d..7003e29 100644 --- a/src/routes/setting/skillManagement/generateDescription.ts +++ b/src/routes/setting/skillManagement/backup/generateDescription.ts @@ -24,7 +24,7 @@ export default router.post( }), async (req, res) => { const { content } = req.body; - const result = await u.Ai.Text("universalAgent").invoke({ + const result = await u.Ai.Text("universalAi").invoke({ system: "你是一个文档摘要助手。根据给定的文档内容生成一句简洁的中文描述(不超过100字),概括文档的核心主题和用途。只输出描述文本,不要添加任何前缀或格式。", messages: [{ role: "user", content: `内容:\n${content}` }], diff --git a/src/routes/setting/skillManagement/backup/getSkillList.ts b/src/routes/setting/skillManagement/backup/getSkillList.ts new file mode 100644 index 0000000..168e60f --- /dev/null +++ b/src/routes/setting/skillManagement/backup/getSkillList.ts @@ -0,0 +1,138 @@ +import express from "express"; +import u from "@/utils"; +import { z } from "zod"; +import { success, error } from "@/lib/responseFormat"; +import { validateFields } from "@/middleware/middleware"; +import fs from "fs"; +import path from "path"; + +const router = express.Router(); + +export default router.post( + "/", + validateFields({ + page: z.number().int().min(1).default(1), + limit: z.number().int().min(1).max(100).default(20), + search: z.string().optional().default(""), + type: z.enum(["main", "references"]).optional(), + attributions: z.array(z.string()).optional(), + }), + async (req, res) => { + const { page, limit, search, type, attributions } = req.body; + const offset = (page - 1) * limit; + + let query = u.db("o_skillList"); + let countQuery = u.db("o_skillList"); + + // 搜索条件 + if (search) { + const searchPattern = `%${search}%`; + const whereBuilder = (builder: any) => { + builder + .where("name", "like", searchPattern) + .orWhere("path", "like", searchPattern) + .orWhere("description", "like", searchPattern); + }; + query = query.where(whereBuilder); + countQuery = countQuery.where(whereBuilder); + } + + // type 筛选条件 + if (type) { + query = query.where("type", type); + countQuery = countQuery.where("type", type); + } + + // attributions 筛选条件 + if (attributions && attributions.length > 0) { + const attributionSubQuery = function (this: any) { + this.select("skillId") + .from("o_skillAttribution") + .whereIn("attribution", attributions); + }; + query = query.whereIn("id", attributionSubQuery); + countQuery = countQuery.whereIn("id", attributionSubQuery); + } + + // 查询总数(在所有筛选条件应用后) + const [{ count }]: any = await countQuery.count("* as count"); + + // 查询列表 + const list = await query + .select("*") + .orderByRaw( + ` + CASE type WHEN 'main' THEN 1 ELSE 0 END ASC, + CASE WHEN id NOT IN (SELECT skillId FROM o_skillAttribution) THEN 0 ELSE 1 END ASC, + CASE WHEN state = 1 THEN 1 ELSE 0 END ASC, + updateTime DESC + ` + ) + .limit(limit) + .offset(offset); + + // 查询每个技能的归属 + const skillIds = list.map((item: any) => item.id); + const attributionsList = await u + .db("o_skillAttribution") + .whereIn("skillId", skillIds) + .select("skillId", "attribution"); + + // 将归属信息合并到列表中 + const attributionMap = new Map(); + for (const attr of attributionsList) { + if (!attributionMap.has(attr.skillId!)) { + attributionMap.set(attr.skillId!, []); + } + attributionMap.get(attr.skillId!)!.push(attr.attribution!); + } + + // 记录需要更新state的技能id + const missingFileIds: string[] = []; + + const listWithAttributions = list.map((item: any) => { + const normalizedPath = (item.path || "").replace(/\\/g, "/"); + const isPrefixedReferencePath = normalizedPath.startsWith("references/"); + const skillFilePath = + item.type === "references" && !isPrefixedReferencePath + ? path.join(u.getPath(["skills", "references"]), item.path!) + : path.join(u.getPath("skills"), item.path!); + + let content = ""; + let state = item.state; + + // 检查文件是否存在 + if (fs.existsSync(skillFilePath)) { + content = fs.readFileSync(skillFilePath, "utf-8"); + } else { + state = -1; + if (item.state !== -1) { + missingFileIds.push(item.id); + } + } + + return { + ...item, + state, + attributions: attributionMap.get(item.id) || [], + content, + embedding: item.embedding ? true : false, + }; + }); + + // 批量更新文件不存在的技能状态 + if (missingFileIds.length > 0) { + await u + .db("o_skillList") + .whereIn("id", missingFileIds) + .update({ state: -1 }); + } + + res.status(200).send( + success({ + list: listWithAttributions, + total: Number(count), + }) + ); + } +); \ No newline at end of file diff --git a/src/routes/setting/skillManagement/scanSkills.ts b/src/routes/setting/skillManagement/backup/scanSkills.ts similarity index 100% rename from src/routes/setting/skillManagement/scanSkills.ts rename to src/routes/setting/skillManagement/backup/scanSkills.ts diff --git a/src/routes/setting/skillManagement/updateSkill.ts b/src/routes/setting/skillManagement/backup/updateSkill.ts similarity index 100% rename from src/routes/setting/skillManagement/updateSkill.ts rename to src/routes/setting/skillManagement/backup/updateSkill.ts diff --git a/src/routes/setting/skillManagement/getSkillList.ts b/src/routes/setting/skillManagement/getSkillList.ts index 168e60f..99bf437 100644 --- a/src/routes/setting/skillManagement/getSkillList.ts +++ b/src/routes/setting/skillManagement/getSkillList.ts @@ -8,131 +8,6 @@ import path from "path"; const router = express.Router(); -export default router.post( - "/", - validateFields({ - page: z.number().int().min(1).default(1), - limit: z.number().int().min(1).max(100).default(20), - search: z.string().optional().default(""), - type: z.enum(["main", "references"]).optional(), - attributions: z.array(z.string()).optional(), - }), - async (req, res) => { - const { page, limit, search, type, attributions } = req.body; - const offset = (page - 1) * limit; - - let query = u.db("o_skillList"); - let countQuery = u.db("o_skillList"); - - // 搜索条件 - if (search) { - const searchPattern = `%${search}%`; - const whereBuilder = (builder: any) => { - builder - .where("name", "like", searchPattern) - .orWhere("path", "like", searchPattern) - .orWhere("description", "like", searchPattern); - }; - query = query.where(whereBuilder); - countQuery = countQuery.where(whereBuilder); - } - - // type 筛选条件 - if (type) { - query = query.where("type", type); - countQuery = countQuery.where("type", type); - } - - // attributions 筛选条件 - if (attributions && attributions.length > 0) { - const attributionSubQuery = function (this: any) { - this.select("skillId") - .from("o_skillAttribution") - .whereIn("attribution", attributions); - }; - query = query.whereIn("id", attributionSubQuery); - countQuery = countQuery.whereIn("id", attributionSubQuery); - } - - // 查询总数(在所有筛选条件应用后) - const [{ count }]: any = await countQuery.count("* as count"); - - // 查询列表 - const list = await query - .select("*") - .orderByRaw( - ` - CASE type WHEN 'main' THEN 1 ELSE 0 END ASC, - CASE WHEN id NOT IN (SELECT skillId FROM o_skillAttribution) THEN 0 ELSE 1 END ASC, - CASE WHEN state = 1 THEN 1 ELSE 0 END ASC, - updateTime DESC - ` - ) - .limit(limit) - .offset(offset); - - // 查询每个技能的归属 - const skillIds = list.map((item: any) => item.id); - const attributionsList = await u - .db("o_skillAttribution") - .whereIn("skillId", skillIds) - .select("skillId", "attribution"); - - // 将归属信息合并到列表中 - const attributionMap = new Map(); - for (const attr of attributionsList) { - if (!attributionMap.has(attr.skillId!)) { - attributionMap.set(attr.skillId!, []); - } - attributionMap.get(attr.skillId!)!.push(attr.attribution!); - } - - // 记录需要更新state的技能id - const missingFileIds: string[] = []; - - const listWithAttributions = list.map((item: any) => { - const normalizedPath = (item.path || "").replace(/\\/g, "/"); - const isPrefixedReferencePath = normalizedPath.startsWith("references/"); - const skillFilePath = - item.type === "references" && !isPrefixedReferencePath - ? path.join(u.getPath(["skills", "references"]), item.path!) - : path.join(u.getPath("skills"), item.path!); - - let content = ""; - let state = item.state; - - // 检查文件是否存在 - if (fs.existsSync(skillFilePath)) { - content = fs.readFileSync(skillFilePath, "utf-8"); - } else { - state = -1; - if (item.state !== -1) { - missingFileIds.push(item.id); - } - } - - return { - ...item, - state, - attributions: attributionMap.get(item.id) || [], - content, - embedding: item.embedding ? true : false, - }; - }); - - // 批量更新文件不存在的技能状态 - if (missingFileIds.length > 0) { - await u - .db("o_skillList") - .whereIn("id", missingFileIds) - .update({ state: -1 }); - } - - res.status(200).send( - success({ - list: listWithAttributions, - total: Number(count), - }) - ); - } -); \ No newline at end of file +export default router.post("/", validateFields({}), async (req, res) => { + res.status(200).send(success({})); +}); diff --git a/src/types/database.d.ts b/src/types/database.d.ts index b49367a..61403b9 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,4 +1,4 @@ -// @db-hash 8aa6e47033e9f59d1f8b797d5b4fccd3 +// @db-hash dd33f188acbdc629e015ba7017c20c78 //该文件由脚本自动生成,请勿手动修改 export interface memories { @@ -21,7 +21,7 @@ export interface o_agentDeploy { 'model'?: string | null; 'modelName'?: string | null; 'name'?: string | null; - 'vendorId'?: number | null; + 'vendorId'?: string | null; } export interface o_agentWorkData { 'createTime'?: number | null; @@ -111,6 +111,7 @@ export interface o_project { 'createTime'?: number | null; 'id'?: number | null; 'imageModel'?: string | null; + 'imageQuality'?: string | null; 'intro'?: string | null; 'name'?: string | null; 'projectType'?: string | null; @@ -142,22 +143,6 @@ export interface o_setting { 'key'?: string | null; 'value'?: string | null; } -export interface o_skillAttribution { - 'attribution'?: string; - 'skillId'?: string; -} -export interface o_skillList { - 'createTime': number; - 'description': string; - 'embedding'?: string | null; - 'id'?: string; - 'md5': string; - 'name': string; - 'path': string; - 'state': number; - 'type': string; - 'updateTime': number; -} export interface o_storyboard { 'camera'?: string | null; 'createTime'?: number | null; @@ -249,8 +234,6 @@ export interface DB { "o_script": o_script; "o_scriptAssets": o_scriptAssets; "o_setting": o_setting; - "o_skillAttribution": o_skillAttribution; - "o_skillList": o_skillList; "o_storyboard": o_storyboard; "o_tasks": o_tasks; "o_user": o_user;