# Conflicts:
#	src/types/database.d.ts
This commit is contained in:
ACT丶流星雨 2026-03-27 21:38:00 +08:00
commit b099017862
25 changed files with 1896 additions and 9481 deletions

8307
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -52,6 +52,7 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"custom-electron-titlebar": "^4.2.8", "custom-electron-titlebar": "^4.2.8",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"electron-rebuild": "^3.2.9",
"express": "^5.2.1", "express": "^5.2.1",
"express-ws": "^5.0.2", "express-ws": "^5.0.2",
"fast-glob": "^3.3.3", "fast-glob": "^3.3.3",

View File

@ -153,6 +153,14 @@ app.whenReady().then(async () => {
app.exit(0); app.exit(0);
return { ok: true }; return { ok: true };
}, },
apprestart: () => {
// 延迟执行,让响应先返回给前端
setTimeout(() => {
app.relaunch();
app.exit(0);
}, 500);
return { ok: true, message: "应用即将重启" };
},
windowismaximized: () => ({ windowismaximized: () => ({
maximized: mainWindow?.isMaximized() ?? false, maximized: mainWindow?.isMaximized() ?? false,
}), }),

View File

@ -78,7 +78,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
modelName: "", modelName: "",
vendorId: null, vendorId: null,
key: "scriptAgent", key: "scriptAgent",
name: "剧本Agent", name: "剧本AI",
desc: "用于读取原文生成故事骨架、改编策略,建议使用具备强大文本理解和生成能力的模型", desc: "用于读取原文生成故事骨架、改编策略,建议使用具备强大文本理解和生成能力的模型",
disabled: false, disabled: false,
}, },
@ -87,7 +87,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
modelName: "", modelName: "",
vendorId: null, vendorId: null,
key: "productionAgent", key: "productionAgent",
name: "生产Agent", name: "生产AI",
desc: "对工作流进行调度和管理,建议使用具备较强的逻辑推理和任务管理能力的模型", desc: "对工作流进行调度和管理,建议使用具备较强的逻辑推理和任务管理能力的模型",
disabled: false, disabled: false,
}, },
@ -96,7 +96,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
modelName: "", modelName: "",
vendorId: null, vendorId: null,
key: "universalAgent", key: "universalAgent",
name: "通用Agent", name: "通用AI",
desc: "用于小说事件提取、资产提示词生成、台词提取等边缘功能,建议使用具备较强文本处理能力的模型", desc: "用于小说事件提取、资产提示词生成、台词提取等边缘功能,建议使用具备较强文本处理能力的模型",
disabled: false, disabled: false,
}, },
@ -184,6 +184,18 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
}, },
initData: async (knex) => {}, initData: async (knex) => {},
}, },
//提示词表
{
name: "o_prompt",
builder: (table) => {
table.integer("id").notNullable();
table.string("name");
table.text("rompt");
table.primary(["id"]);
table.unique(["id"]);
},
initData: async (knex) => {},
},
//小说原文表 //小说原文表
{ {
name: "o_novel", name: "o_novel",
@ -276,6 +288,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
table.integer("assetsId"); table.integer("assetsId");
table.integer("projectId"); table.integer("projectId");
table.integer("startTime"); table.integer("startTime");
table.string("promptState");
table.primary(["id"]); table.primary(["id"]);
table.unique(["id"]); table.unique(["id"]);
}, },

View File

@ -1,4 +1,4 @@
// @routes-hash 57463134da0d81d65d10c163ee8a2b26 // @routes-hash 63d067de9d3f97b0602ef91a69334bc8
import { Express } from "express"; import { Express } from "express";
import route1 from "./routes/agents/clearMemory"; import route1 from "./routes/agents/clearMemory";
@ -14,94 +14,97 @@ import route10 from "./routes/assets/delAssets";
import route11 from "./routes/assets/getAssetsApi"; import route11 from "./routes/assets/getAssetsApi";
import route12 from "./routes/assets/getImage"; import route12 from "./routes/assets/getImage";
import route13 from "./routes/assets/getMaterialData"; import route13 from "./routes/assets/getMaterialData";
import route14 from "./routes/assets/saveAssets"; import route14 from "./routes/assets/pollingImageAssets";
import route15 from "./routes/assets/updateAssets"; import route15 from "./routes/assets/pollingPromptAssets";
import route16 from "./routes/assets/uploadClip"; import route16 from "./routes/assets/saveAssets";
import route17 from "./routes/assetsGenerate/generateAssets"; import route17 from "./routes/assets/updateAssets";
import route18 from "./routes/assetsGenerate/polishAssetsPrompt"; import route18 from "./routes/assets/uploadClip";
import route19 from "./routes/cornerScape/getAllAssets"; import route19 from "./routes/assetsGenerate/generateAssets";
import route20 from "./routes/general/generalStatistics"; import route20 from "./routes/assetsGenerate/polishAssetsPrompt";
import route21 from "./routes/general/getSingleProject"; import route21 from "./routes/cornerScape/getAllAssets";
import route22 from "./routes/general/updateProject"; import route22 from "./routes/general/generalStatistics";
import route23 from "./routes/login/login"; import route23 from "./routes/general/getSingleProject";
import route24 from "./routes/migrate/migrateData"; import route24 from "./routes/general/updateProject";
import route25 from "./routes/modelSelect/getModelDetail"; import route25 from "./routes/login/login";
import route26 from "./routes/modelSelect/getModelList"; import route26 from "./routes/migrate/migrateData";
import route27 from "./routes/novel/addNovel"; import route27 from "./routes/modelSelect/getModelDetail";
import route28 from "./routes/novel/batchDeleteNovel"; import route28 from "./routes/modelSelect/getModelList";
import route29 from "./routes/novel/delNovel"; import route29 from "./routes/novel/addNovel";
import route30 from "./routes/novel/event/batchDeleteEvent"; import route30 from "./routes/novel/batchDeleteNovel";
import route31 from "./routes/novel/event/deletEvent"; import route31 from "./routes/novel/delNovel";
import route32 from "./routes/novel/event/generateEvents"; import route32 from "./routes/novel/event/batchDeleteEvent";
import route33 from "./routes/novel/event/getEvent"; import route33 from "./routes/novel/event/deletEvent";
import route34 from "./routes/novel/getNovel"; import route34 from "./routes/novel/event/generateEvents";
import route35 from "./routes/novel/getNovelEventState"; import route35 from "./routes/novel/event/getEvent";
import route36 from "./routes/novel/getNovelIndex"; import route36 from "./routes/novel/getNovel";
import route37 from "./routes/novel/updateNovel"; import route37 from "./routes/novel/getNovelEventState";
import route38 from "./routes/other/deleteAllData"; import route38 from "./routes/novel/getNovelIndex";
import route39 from "./routes/other/getVersion"; import route39 from "./routes/novel/updateNovel";
import route40 from "./routes/production/assets/getAssetsData"; import route40 from "./routes/other/deleteAllData";
import route41 from "./routes/production/editImage/generateFlowImage"; import route41 from "./routes/other/getVersion";
import route42 from "./routes/production/editImage/getImageFlow"; import route42 from "./routes/production/assets/getAssetsData";
import route43 from "./routes/production/editImage/saveImageFlow"; import route43 from "./routes/production/editImage/generateFlowImage";
import route44 from "./routes/production/editImage/updateImageFlow"; import route44 from "./routes/production/editImage/getImageFlow";
import route45 from "./routes/production/exportImage"; import route45 from "./routes/production/editImage/saveImageFlow";
import route46 from "./routes/production/getFlowData"; import route46 from "./routes/production/editImage/updateImageFlow";
import route47 from "./routes/production/getProductionData"; import route47 from "./routes/production/exportImage";
import route48 from "./routes/production/getStoryboardData"; import route48 from "./routes/production/getFlowData";
import route49 from "./routes/production/saveFlowData"; import route49 from "./routes/production/getProductionData";
import route50 from "./routes/production/storyboard/downPreviewImage"; import route50 from "./routes/production/getStoryboardData";
import route51 from "./routes/production/storyboard/getStoryboardData"; import route51 from "./routes/production/saveFlowData";
import route52 from "./routes/production/storyboard/previewImage"; import route52 from "./routes/production/storyboard/downPreviewImage";
import route53 from "./routes/production/workbench/confirmSelection"; import route53 from "./routes/production/storyboard/getStoryboardData";
import route54 from "./routes/production/workbench/delVideo"; import route54 from "./routes/production/storyboard/previewImage";
import route55 from "./routes/production/workbench/generateVideo"; import route55 from "./routes/production/workbench/confirmSelection";
import route56 from "./routes/production/workbench/getChatLines"; import route56 from "./routes/production/workbench/delVideo";
import route57 from "./routes/production/workbench/getVideoModelDetail"; import route57 from "./routes/production/workbench/generateVideo";
import route58 from "./routes/production/workbench/videoPolling"; import route58 from "./routes/production/workbench/getChatLines";
import route59 from "./routes/project/addProject"; import route59 from "./routes/production/workbench/getVideoModelDetail";
import route60 from "./routes/project/delProject"; import route60 from "./routes/production/workbench/videoPolling";
import route61 from "./routes/project/editProject"; import route61 from "./routes/project/addProject";
import route62 from "./routes/project/getProject"; import route62 from "./routes/project/delProject";
import route63 from "./routes/script/addScript"; import route63 from "./routes/project/editProject";
import route64 from "./routes/script/delScript"; import route64 from "./routes/project/getProject";
import route65 from "./routes/script/exportScript"; import route65 from "./routes/script/addScript";
import route66 from "./routes/script/extractAssets"; import route66 from "./routes/script/delScript";
import route67 from "./routes/script/getScrptApi"; import route67 from "./routes/script/exportScript";
import route68 from "./routes/script/updateScript"; import route68 from "./routes/script/extractAssets";
import route69 from "./routes/scriptAgent/getPlanData"; import route69 from "./routes/script/getScrptApi";
import route70 from "./routes/scriptAgent/setPlanData"; import route70 from "./routes/script/updateScript";
import route71 from "./routes/setting/about/checkUpdate"; import route71 from "./routes/scriptAgent/getPlanData";
import route72 from "./routes/setting/agentDeploy/agentSetKey"; import route72 from "./routes/scriptAgent/setPlanData";
import route73 from "./routes/setting/agentDeploy/deployAgentModel"; import route73 from "./routes/setting/about/checkUpdate";
import route74 from "./routes/setting/agentDeploy/getAgentDeploy"; import route74 from "./routes/setting/agentDeploy/agentSetKey";
import route75 from "./routes/setting/dbConfig/clearData"; import route75 from "./routes/setting/agentDeploy/deployAgentModel";
import route76 from "./routes/setting/dev/getSwitchAiDevTool"; import route76 from "./routes/setting/agentDeploy/getAgentDeploy";
import route77 from "./routes/setting/dev/updateSwitchAiDevTool"; import route77 from "./routes/setting/dbConfig/clearData";
import route78 from "./routes/setting/fileManagement/openFolder"; import route78 from "./routes/setting/dev/getSwitchAiDevTool";
import route79 from "./routes/setting/getTextModel"; import route79 from "./routes/setting/dev/updateSwitchAiDevTool";
import route80 from "./routes/setting/loginConfig/getUser"; import route80 from "./routes/setting/fileManagement/openFolder";
import route81 from "./routes/setting/loginConfig/updateUserPwd"; import route81 from "./routes/setting/getTextModel";
import route82 from "./routes/setting/memoryConfig/delAllMemory"; import route82 from "./routes/setting/loginConfig/getUser";
import route83 from "./routes/setting/memoryConfig/getMemory"; import route83 from "./routes/setting/loginConfig/updateUserPwd";
import route84 from "./routes/setting/memoryConfig/sureMemory"; import route84 from "./routes/setting/memoryConfig/delAllMemory";
import route85 from "./routes/setting/skillManagement/addSkill"; import route85 from "./routes/setting/memoryConfig/getMemory";
import route86 from "./routes/setting/skillManagement/deleteSkill"; import route86 from "./routes/setting/memoryConfig/sureMemory";
import route87 from "./routes/setting/skillManagement/embeddingSkill"; import route87 from "./routes/setting/skillManagement/addSkill";
import route88 from "./routes/setting/skillManagement/generateDescription"; import route88 from "./routes/setting/skillManagement/deleteSkill";
import route89 from "./routes/setting/skillManagement/getSkillList"; import route89 from "./routes/setting/skillManagement/embeddingSkill";
import route90 from "./routes/setting/skillManagement/scanSkills"; import route90 from "./routes/setting/skillManagement/generateDescription";
import route91 from "./routes/setting/skillManagement/updateSkill"; import route91 from "./routes/setting/skillManagement/getSkillList";
import route92 from "./routes/setting/vendorConfig/addVendor"; import route92 from "./routes/setting/skillManagement/scanSkills";
import route93 from "./routes/setting/vendorConfig/deleteVendor"; import route93 from "./routes/setting/skillManagement/updateSkill";
import route94 from "./routes/setting/vendorConfig/getVendorList"; import route94 from "./routes/setting/vendorConfig/addVendor";
import route95 from "./routes/setting/vendorConfig/modelTest"; import route95 from "./routes/setting/vendorConfig/deleteVendor";
import route96 from "./routes/setting/vendorConfig/updateVendor"; import route96 from "./routes/setting/vendorConfig/getVendorList";
import route97 from "./routes/task/getProject"; import route97 from "./routes/setting/vendorConfig/modelTest";
import route98 from "./routes/task/getTaskApi"; import route98 from "./routes/setting/vendorConfig/updateCode";
import route99 from "./routes/task/getTaskCategories"; import route99 from "./routes/setting/vendorConfig/updateVendor";
import route100 from "./routes/task/taskDetails"; import route100 from "./routes/task/getProject";
import route101 from "./routes/test/test"; import route101 from "./routes/task/getTaskApi";
import route102 from "./routes/task/getTaskCategories";
import route103 from "./routes/task/taskDetails";
import route104 from "./routes/test/test";
export default async (app: Express) => { export default async (app: Express) => {
app.use("/api/agents/clearMemory", route1); app.use("/api/agents/clearMemory", route1);
@ -117,92 +120,95 @@ export default async (app: Express) => {
app.use("/api/assets/getAssetsApi", route11); app.use("/api/assets/getAssetsApi", route11);
app.use("/api/assets/getImage", route12); app.use("/api/assets/getImage", route12);
app.use("/api/assets/getMaterialData", route13); app.use("/api/assets/getMaterialData", route13);
app.use("/api/assets/saveAssets", route14); app.use("/api/assets/pollingImageAssets", route14);
app.use("/api/assets/updateAssets", route15); app.use("/api/assets/pollingPromptAssets", route15);
app.use("/api/assets/uploadClip", route16); app.use("/api/assets/saveAssets", route16);
app.use("/api/assetsGenerate/generateAssets", route17); app.use("/api/assets/updateAssets", route17);
app.use("/api/assetsGenerate/polishAssetsPrompt", route18); app.use("/api/assets/uploadClip", route18);
app.use("/api/cornerScape/getAllAssets", route19); app.use("/api/assetsGenerate/generateAssets", route19);
app.use("/api/general/generalStatistics", route20); app.use("/api/assetsGenerate/polishAssetsPrompt", route20);
app.use("/api/general/getSingleProject", route21); app.use("/api/cornerScape/getAllAssets", route21);
app.use("/api/general/updateProject", route22); app.use("/api/general/generalStatistics", route22);
app.use("/api/login/login", route23); app.use("/api/general/getSingleProject", route23);
app.use("/api/migrate/migrateData", route24); app.use("/api/general/updateProject", route24);
app.use("/api/modelSelect/getModelDetail", route25); app.use("/api/login/login", route25);
app.use("/api/modelSelect/getModelList", route26); app.use("/api/migrate/migrateData", route26);
app.use("/api/novel/addNovel", route27); app.use("/api/modelSelect/getModelDetail", route27);
app.use("/api/novel/batchDeleteNovel", route28); app.use("/api/modelSelect/getModelList", route28);
app.use("/api/novel/delNovel", route29); app.use("/api/novel/addNovel", route29);
app.use("/api/novel/event/batchDeleteEvent", route30); app.use("/api/novel/batchDeleteNovel", route30);
app.use("/api/novel/event/deletEvent", route31); app.use("/api/novel/delNovel", route31);
app.use("/api/novel/event/generateEvents", route32); app.use("/api/novel/event/batchDeleteEvent", route32);
app.use("/api/novel/event/getEvent", route33); app.use("/api/novel/event/deletEvent", route33);
app.use("/api/novel/getNovel", route34); app.use("/api/novel/event/generateEvents", route34);
app.use("/api/novel/getNovelEventState", route35); app.use("/api/novel/event/getEvent", route35);
app.use("/api/novel/getNovelIndex", route36); app.use("/api/novel/getNovel", route36);
app.use("/api/novel/updateNovel", route37); app.use("/api/novel/getNovelEventState", route37);
app.use("/api/other/deleteAllData", route38); app.use("/api/novel/getNovelIndex", route38);
app.use("/api/other/getVersion", route39); app.use("/api/novel/updateNovel", route39);
app.use("/api/production/assets/getAssetsData", route40); app.use("/api/other/deleteAllData", route40);
app.use("/api/production/editImage/generateFlowImage", route41); app.use("/api/other/getVersion", route41);
app.use("/api/production/editImage/getImageFlow", route42); app.use("/api/production/assets/getAssetsData", route42);
app.use("/api/production/editImage/saveImageFlow", route43); app.use("/api/production/editImage/generateFlowImage", route43);
app.use("/api/production/editImage/updateImageFlow", route44); app.use("/api/production/editImage/getImageFlow", route44);
app.use("/api/production/exportImage", route45); app.use("/api/production/editImage/saveImageFlow", route45);
app.use("/api/production/getFlowData", route46); app.use("/api/production/editImage/updateImageFlow", route46);
app.use("/api/production/getProductionData", route47); app.use("/api/production/exportImage", route47);
app.use("/api/production/getStoryboardData", route48); app.use("/api/production/getFlowData", route48);
app.use("/api/production/saveFlowData", route49); app.use("/api/production/getProductionData", route49);
app.use("/api/production/storyboard/downPreviewImage", route50); app.use("/api/production/getStoryboardData", route50);
app.use("/api/production/storyboard/getStoryboardData", route51); app.use("/api/production/saveFlowData", route51);
app.use("/api/production/storyboard/previewImage", route52); app.use("/api/production/storyboard/downPreviewImage", route52);
app.use("/api/production/workbench/confirmSelection", route53); app.use("/api/production/storyboard/getStoryboardData", route53);
app.use("/api/production/workbench/delVideo", route54); app.use("/api/production/storyboard/previewImage", route54);
app.use("/api/production/workbench/generateVideo", route55); app.use("/api/production/workbench/confirmSelection", route55);
app.use("/api/production/workbench/getChatLines", route56); app.use("/api/production/workbench/delVideo", route56);
app.use("/api/production/workbench/getVideoModelDetail", route57); app.use("/api/production/workbench/generateVideo", route57);
app.use("/api/production/workbench/videoPolling", route58); app.use("/api/production/workbench/getChatLines", route58);
app.use("/api/project/addProject", route59); app.use("/api/production/workbench/getVideoModelDetail", route59);
app.use("/api/project/delProject", route60); app.use("/api/production/workbench/videoPolling", route60);
app.use("/api/project/editProject", route61); app.use("/api/project/addProject", route61);
app.use("/api/project/getProject", route62); app.use("/api/project/delProject", route62);
app.use("/api/script/addScript", route63); app.use("/api/project/editProject", route63);
app.use("/api/script/delScript", route64); app.use("/api/project/getProject", route64);
app.use("/api/script/exportScript", route65); app.use("/api/script/addScript", route65);
app.use("/api/script/extractAssets", route66); app.use("/api/script/delScript", route66);
app.use("/api/script/getScrptApi", route67); app.use("/api/script/exportScript", route67);
app.use("/api/script/updateScript", route68); app.use("/api/script/extractAssets", route68);
app.use("/api/scriptAgent/getPlanData", route69); app.use("/api/script/getScrptApi", route69);
app.use("/api/scriptAgent/setPlanData", route70); app.use("/api/script/updateScript", route70);
app.use("/api/setting/about/checkUpdate", route71); app.use("/api/scriptAgent/getPlanData", route71);
app.use("/api/setting/agentDeploy/agentSetKey", route72); app.use("/api/scriptAgent/setPlanData", route72);
app.use("/api/setting/agentDeploy/deployAgentModel", route73); app.use("/api/setting/about/checkUpdate", route73);
app.use("/api/setting/agentDeploy/getAgentDeploy", route74); app.use("/api/setting/agentDeploy/agentSetKey", route74);
app.use("/api/setting/dbConfig/clearData", route75); app.use("/api/setting/agentDeploy/deployAgentModel", route75);
app.use("/api/setting/dev/getSwitchAiDevTool", route76); app.use("/api/setting/agentDeploy/getAgentDeploy", route76);
app.use("/api/setting/dev/updateSwitchAiDevTool", route77); app.use("/api/setting/dbConfig/clearData", route77);
app.use("/api/setting/fileManagement/openFolder", route78); app.use("/api/setting/dev/getSwitchAiDevTool", route78);
app.use("/api/setting/getTextModel", route79); app.use("/api/setting/dev/updateSwitchAiDevTool", route79);
app.use("/api/setting/loginConfig/getUser", route80); app.use("/api/setting/fileManagement/openFolder", route80);
app.use("/api/setting/loginConfig/updateUserPwd", route81); app.use("/api/setting/getTextModel", route81);
app.use("/api/setting/memoryConfig/delAllMemory", route82); app.use("/api/setting/loginConfig/getUser", route82);
app.use("/api/setting/memoryConfig/getMemory", route83); app.use("/api/setting/loginConfig/updateUserPwd", route83);
app.use("/api/setting/memoryConfig/sureMemory", route84); app.use("/api/setting/memoryConfig/delAllMemory", route84);
app.use("/api/setting/skillManagement/addSkill", route85); app.use("/api/setting/memoryConfig/getMemory", route85);
app.use("/api/setting/skillManagement/deleteSkill", route86); app.use("/api/setting/memoryConfig/sureMemory", route86);
app.use("/api/setting/skillManagement/embeddingSkill", route87); app.use("/api/setting/skillManagement/addSkill", route87);
app.use("/api/setting/skillManagement/generateDescription", route88); app.use("/api/setting/skillManagement/deleteSkill", route88);
app.use("/api/setting/skillManagement/getSkillList", route89); app.use("/api/setting/skillManagement/embeddingSkill", route89);
app.use("/api/setting/skillManagement/scanSkills", route90); app.use("/api/setting/skillManagement/generateDescription", route90);
app.use("/api/setting/skillManagement/updateSkill", route91); app.use("/api/setting/skillManagement/getSkillList", route91);
app.use("/api/setting/vendorConfig/addVendor", route92); app.use("/api/setting/skillManagement/scanSkills", route92);
app.use("/api/setting/vendorConfig/deleteVendor", route93); app.use("/api/setting/skillManagement/updateSkill", route93);
app.use("/api/setting/vendorConfig/getVendorList", route94); app.use("/api/setting/vendorConfig/addVendor", route94);
app.use("/api/setting/vendorConfig/modelTest", route95); app.use("/api/setting/vendorConfig/deleteVendor", route95);
app.use("/api/setting/vendorConfig/updateVendor", route96); app.use("/api/setting/vendorConfig/getVendorList", route96);
app.use("/api/task/getProject", route97); app.use("/api/setting/vendorConfig/modelTest", route97);
app.use("/api/task/getTaskApi", route98); app.use("/api/setting/vendorConfig/updateCode", route98);
app.use("/api/task/getTaskCategories", route99); app.use("/api/setting/vendorConfig/updateVendor", route99);
app.use("/api/task/taskDetails", route100); app.use("/api/task/getProject", route100);
app.use("/api/test/test", route101); app.use("/api/task/getTaskApi", route101);
app.use("/api/task/getTaskCategories", route102);
app.use("/api/task/taskDetails", route103);
app.use("/api/test/test", route104);
} }

View File

@ -21,7 +21,7 @@ export default router.post(
let query = u let query = u
.db("o_assets") .db("o_assets")
.leftJoin("o_image", "o_assets.imageId", "o_image.id") .leftJoin("o_image", "o_assets.imageId", "o_image.id")
.select("o_assets.*", "o_image.filePath") .select("o_assets.*", "o_image.filePath", "o_image.state")
.where("o_assets.projectId", projectId) .where("o_assets.projectId", projectId)
.andWhere("o_assets.type", type); .andWhere("o_assets.type", type);
if (name) { if (name) {
@ -34,7 +34,7 @@ export default router.post(
let childQuery = u let childQuery = u
.db("o_assets") .db("o_assets")
.leftJoin("o_image", "o_assets.imageId", "o_image.id") .leftJoin("o_image", "o_assets.imageId", "o_image.id")
.select("o_assets.*", "o_image.filePath") .select("o_assets.*", "o_image.filePath", "o_image.state")
.where("o_assets.projectId", projectId) .where("o_assets.projectId", projectId)
.andWhere("o_assets.type", type) .andWhere("o_assets.type", type)
.whereNotNull("o_assets.assetsId"); .whereNotNull("o_assets.assetsId");

View File

@ -0,0 +1,28 @@
import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
ids: z.array(z.number()),
}),
async (req, res) => {
const { ids } = req.body;
const data = await u
.db("o_assets")
.leftJoin("o_image", "o_assets.id", "o_image.assetsId")
.whereIn("o_assets.id", ids)
.select("o_image.state", "o_assets.id", "o_image.filePath");
const result = await Promise.all(
data.map(async (item: any) => ({
...item,
filePath: item.filePath ? await u.oss.getFileUrl(item.filePath) : null,
})),
);
res.status(200).send(success(result));
},
);

View File

@ -0,0 +1,18 @@
import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
ids: z.array(z.number()),
}),
async (req, res) => {
const { ids } = req.body;
const data = await u.db("o_assets").whereIn("id", ids).select("*");
res.status(200).send(success(data));
},
);

View File

@ -33,7 +33,7 @@ export default router.post(
assetsId: id, assetsId: id,
filePath: savePath, filePath: savePath,
type: type, type: type,
state: "生成成功", state: "已完成",
}); });
// 更新资产表图片为新图片 // 更新资产表图片为新图片
await u await u

View File

@ -50,7 +50,7 @@ export default router.post(
filePath: savePath, filePath: savePath,
type, type,
assetsId: id, assetsId: id,
state: "1", state: '已完成',
}); });
await u.db("o_assets").where("id", id).update({ await u.db("o_assets").where("id", id).update({
imageId: imageId, imageId: imageId,

View File

@ -87,6 +87,7 @@ export default router.post("/", validateFields(requestSchema), async (req, res)
state: "生成中", state: "生成中",
assetsId: id, assetsId: id,
}); });
await u.db("o_assets").where("id", id).update({ imageId });
// 3. 准备生成参数 // 3. 准备生成参数
const imagePath = `/${projectId}/${cfg.dir}/${uuidv4()}.jpg`; const imagePath = `/${projectId}/${cfg.dir}/${uuidv4()}.jpg`;
@ -106,7 +107,7 @@ export default router.post("/", validateFields(requestSchema), async (req, res)
describe, describe,
projectId, projectId,
relatedObjects: JSON.stringify(relatedObjects), relatedObjects: JSON.stringify(relatedObjects),
}); })
aiImage.save(imagePath); aiImage.save(imagePath);
// 5. 更新记录 & 返回结果 // 5. 更新记录 & 返回结果
@ -114,7 +115,7 @@ export default router.post("/", validateFields(requestSchema), async (req, res)
if (!imageData) return res.status(500).send("资产已被删除"); if (!imageData) return res.status(500).send("资产已被删除");
await u.db("o_image").where("id", imageId).update({ await u.db("o_image").where("id", imageId).update({
state: "生成成功", state: "已完成",
filePath: imagePath, filePath: imagePath,
type, type,
model: model.split(":")[1], model: model.split(":")[1],

View File

@ -61,6 +61,7 @@ export default router.post(
if (!project) return res.status(500).send(success({ message: "项目为空" })); if (!project) return res.status(500).send(success({ message: "项目为空" }));
const allOutlineDataList: { data: string }[] = await u.db("o_outline").where("projectId", projectId).select("data"); const allOutlineDataList: { data: string }[] = await u.db("o_outline").where("projectId", projectId).select("data");
await u.db("o_assets").where("id", assetsId).update({ promptState: "生成中" });
const itemMap: Record<string, ResultItem> = {}; const itemMap: Record<string, ResultItem> = {};
@ -124,7 +125,7 @@ export default router.post(
})) as any; })) as any;
if (!_output) return res.status(500).send("失败"); if (!_output) return res.status(500).send("失败");
await u.db("o_assets").where("id", assetsId).update({ prompt: _output }); await u.db("o_assets").where("id", assetsId).update({ prompt: _output, promptState: "已完成" });
res.status(200).send(success({ prompt: _output, assetsId })); res.status(200).send(success({ prompt: _output, assetsId }));
} catch (e: any) { } catch (e: any) {

View File

@ -12,32 +12,24 @@ export default router.post(
}), }),
async (req, res) => { async (req, res) => {
const { type } = req.body; const { type } = req.body;
const data = await u.db("o_vendorConfig").select("id", "models", "name").first(); const dataList = await u.db("o_vendorConfig").select("id", "models", "name");
if (!data) { if (!dataList || dataList.length === 0) {
return res.status(404).send({ error: "模型未找到" }); return res.status(404).send({ error: "模型未找到" });
} }
const models = JSON.parse(data.models!); const result = dataList.flatMap((data) => {
if (type === "all") { const models = JSON.parse(data.models!);
const allData = models const filtered =
.filter((item: { type: string }) => item.type !== "video") type === "all"
.map((item: { name: string; modelName: string; type: string }) => ({ ? models.filter((item: { type: string }) => item.type !== "video")
id: data.id, : models.filter((item: { type: string }) => item.type === type);
label: item.name, return filtered.map((item: { name: string; modelName: string; type: string }) => ({
value: item.modelName,
type: item.type,
name: data.name,
}));
return res.status(200).send(success(allData));
}
const filteredData = models
.filter((item: { type: string }) => item.type === type)
.map((item: { name: string; modelName: string; type: string }) => ({
id: data.id, id: data.id,
label: item.name, label: item.name,
value: item.modelName, value: item.modelName,
type: item.type, type: item.type,
name: data.name, name: data.name,
})); }));
res.status(200).send(success(filteredData)); });
res.status(200).send(success(result));
}, },
); );

View File

@ -2,10 +2,10 @@ import express from "express";
import u from "@/utils"; import u from "@/utils";
import { z } from "zod"; import { z } from "zod";
import { error, success } from "@/lib/responseFormat"; import { error, success } from "@/lib/responseFormat";
import compressing from "compressing";
import { validateFields } from "@/middleware/middleware"; import { validateFields } from "@/middleware/middleware";
import { useSkill } from "@/utils/agent/skillsTools"; import { useSkill } from "@/utils/agent/skillsTools";
import { Output, tool } from "ai"; import { tool } from "ai";
import { o_script } from "@/types/database";
const router = express.Router(); const router = express.Router();
export const AssetSchema = z.object({ export const AssetSchema = z.object({
@ -14,79 +14,166 @@ export const AssetSchema = z.object({
desc: z.string().describe("资产描述"), desc: z.string().describe("资产描述"),
type: z.enum(["role", "tool", "scene"]).describe("资产类型"), type: z.enum(["role", "tool", "scene"]).describe("资产类型"),
}); });
type Asset = z.infer<typeof AssetSchema>;
/** 控制并发的辅助函数 */
async function pMap<T, R>(items: T[], fn: (item: T) => Promise<R>, concurrency: number): Promise<R[]> {
const results: R[] = [];
let index = 0;
async function worker() {
while (index < items.length) {
const i = index++;
results[i] = await fn(items[i]);
}
}
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
return results;
}
export default router.post( export default router.post(
"/", "/",
validateFields({ validateFields({
scriptIds: z.array(z.number()), scriptIds: z.array(z.number()),
projectId: z.number(), projectId: z.number(),
concurrency: z.number().min(1).max(20).optional(),
}), }),
async (req, res) => { async (req, res) => {
const { scriptIds, projectId } = req.body; const { scriptIds, projectId, concurrency = 3 } = req.body;
if (!scriptIds.length) return res.status(400).send(error("请先选择剧本")); if (!scriptIds.length) return res.status(400).send(error("请先选择剧本"));
const scripts = await u.db("o_script").whereIn("id", scriptIds); const scripts = await u.db("o_script").whereIn("id", scriptIds);
const intansce = u.Ai.Text("universalAgent"); const intansce = u.Ai.Text("universalAgent");
const novelData = await u.db("o_novel").where("projectId", projectId).select("chapterData"); const novelData = await u.db("o_novel").where("projectId", projectId).select("chapterData");
if (!novelData || novelData.length === 0) return res.status(400).send(error("请先上传小说")); if (!novelData || novelData.length === 0) return res.status(400).send(error("请先上传小说"));
async function getAssets() { // 每个 scriptId 对应提取出的资产列表
return await u.db("o_assets").where("projectId", projectId).select("id", "name"); const scriptAssetsMap = new Map<number, Asset[]>();
}
for (const scriptId of scriptIds) {
const resultTool = tool({
description: "返回结果时必须调用这个工具,",
inputSchema: z.object({
assetsList: z.array(AssetSchema).describe("剧本所使用资产列表,注意不要包含剧本内容,仅为所使用到的 道具、人物、场景、素材"),
}),
execute: async ({ assetsList }) => {
console.log("[tools] set_flowData script", assetsList);
if (assetsList && assetsList.length) {
const assetId = [];
const existingAssets = await getAssets();
for (const i of assetsList) {
if (existingAssets.length) {
const exist = existingAssets.find((j) => j.name === i.name);
if (exist) {
assetId.push(exist.id);
continue;
}
}
const [id] = await u.db("o_assets").insert({
name: i.name,
prompt: i.prompt,
type: i.type,
describe: i.desc,
projectId: projectId,
startTime: Date.now(),
});
assetId.push(id);
}
await u.db("o_scriptAssets").insert(assetId.map((i) => ({ scriptId: scriptId, assetId: i }))); // 构建 scriptId -> script 内容的映射
} const scriptMap = new Map(scripts.map((s: o_script) => [s.id, s]));
return true;
}, const errors: { scriptId: number; error: string }[] = [];
});
try { // 并发提取所有剧本的资产,每个剧本单独跑一次 AI
const skill = await useSkill("universal_agent.md"); await pMap(
const resData = await intansce.invoke({ scriptIds,
messages: [ async (scriptId: number) => {
{ const script = scriptMap.get(scriptId);
role: "system", if (!script) {
content: errors.push({ scriptId, error: "未找到对应剧本" });
skill.prompt + return;
"\n\n提取剧本中涉及的资产角色、场景、道具参考技能 script_assets_extract 规范,结果必须通过 resultTool 工具返回。", }
},
{ // 用闭包收集当前 scriptId 的资产
role: "user", let collected: Asset[] = [];
content: `请根据以下剧本提取对应的剧本资产(角色、场景、道具、素材片段):\n\n${scripts.map((i) => i.content).join("\n\n---\n\n")}`,
}, const resultTool = tool({
], description: "返回结果时必须调用这个工具,",
tools: { ...skill.tools, resultTool }, inputSchema: z.object({
assetsList: z.array(AssetSchema).describe("剧本所使用资产列表,注意不要包含剧本内容,仅为所使用到的 道具、人物、场景、素材"),
}),
execute: async ({ assetsList }) => {
console.log("[tools] set_flowData script", assetsList);
if (assetsList && assetsList.length) {
collected = assetsList;
}
return true;
},
}); });
console.log("%c Line:47 🥝 resData", "background:#2eafb0", resData);
} catch (e) { try {
console.log("%c Line:52 🍢 e", "background:#42b983", e); const skill = await useSkill("universal_agent.md");
await intansce.invoke({
messages: [
{
role: "system",
content:
skill.prompt +
"\n\n提取剧本中涉及的资产角色、场景、道具参考技能 script_assets_extract 规范,结果必须通过 resultTool 工具返回。",
},
{
role: "user",
content: `请根据以下剧本提取对应的剧本资产(角色、场景、道具、素材片段):\n\n${script.content}`,
},
],
tools: { ...skill.tools, resultTool },
});
} catch (e: any) {
const msg = e?.message || String(e);
console.error(`[extractAssets] scriptId=${scriptId} name=${script.name} 提取失败:`, msg);
errors.push({ scriptId, error: script.name + ":" + u.error(e).message });
return;
}
if (!collected.length) {
errors.push({ scriptId, error: "AI 未返回任何资产" });
return;
}
scriptAssetsMap.set(scriptId, collected);
},
concurrency,
);
// 如果全部失败,直接返回错误
if (!scriptAssetsMap.size) {
return res.status(500).send(error("所有剧本资产提取均失败", errors));
}
// 按 name 合并所有资产,同名资产只保留第一个
const mergedAssetsMap = new Map<string, Asset>();
// 同时记录每个资产名称关联的 scriptId 列表
const assetScriptIds = new Map<string, number[]>();
for (const [scriptId, assets] of scriptAssetsMap) {
for (const asset of assets) {
if (!mergedAssetsMap.has(asset.name)) {
mergedAssetsMap.set(asset.name, asset);
}
const ids = assetScriptIds.get(asset.name) || [];
ids.push(scriptId);
assetScriptIds.set(asset.name, ids);
} }
} }
// 一次性查询数据库中已有的资产
const existingAssets = await u.db("o_assets").where("projectId", projectId).select("id", "name");
const existingMap = new Map(existingAssets.map((a) => [a.name!, a.id!]));
// 批量插入不存在的资产
const toInsert = [...mergedAssetsMap.values()].filter((asset) => !existingMap.has(asset.name));
if (toInsert.length) {
await u.db("o_assets").insert(
toInsert.map((asset) => ({
name: asset.name,
prompt: asset.prompt,
type: asset.type,
describe: asset.desc,
projectId: projectId,
startTime: Date.now(),
})),
);
}
// 重新查询所有资产,获取完整的 name -> id 映射
const allAssets = await u.db("o_assets").where("projectId", projectId).select("id", "name");
const nameToId = new Map(allAssets.map((a) => [a.name, a.id]));
// 批量建立 scriptId <-> assetId 的关联
const scriptAssetRows: { scriptId: number; assetId: number }[] = [];
for (const [name, sIds] of assetScriptIds) {
const assetId = nameToId.get(name);
if (assetId) {
for (const sid of sIds) {
scriptAssetRows.push({ scriptId: sid, assetId });
}
}
}
await u.db("o_scriptAssets").whereIn("scriptId", scriptIds).delete();
if (scriptAssetRows.length) {
await u.db("o_scriptAssets").insert(scriptAssetRows);
}
return res.send(success(errors.length ? `部分剧本资产提取失败\n${errors.map((i) => i.error).join("\n")}` : "资产提取完成"));
}, },
); );

View File

@ -23,11 +23,11 @@ export default router.post("/", async (req, res) => {
const currentVersionList = APP_VERSION.split(".").map(Number); const currentVersionList = APP_VERSION.split(".").map(Number);
//对比Major //对比Major
if (taggerList[0] > currentVersionList[0]) { if (taggerList[0] > currentVersionList[0]) {
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: true })); return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: false }));
} }
//对比Minor //对比Minor
if (taggerList[1] > currentVersionList[1]) { if (taggerList[1] > currentVersionList[1]) {
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: true })); return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: false }));
} }
//Patch //Patch
if (taggerList[2] > currentVersionList[2]) { if (taggerList[2] > currentVersionList[2]) {

View File

@ -14,7 +14,7 @@ export default router.post(
const { id } = req.body; const { id } = req.body;
await u.db("o_agentDeploy").whereIn("id", id).where("disabled", "<>", 1).update({ await u.db("o_agentDeploy").whereIn("id", id).where("disabled", "<>", 1).update({
model: "gpt-4.1", model: "gpt-4.1",
modelName: "1:gpt-4.1", modelName: "toonflow:gpt-4.1",
vendorId: 1, vendorId: 1,
}); });
res.status(200).send(success("配置成功")); res.status(200).send(success("配置成功"));

View File

@ -5,15 +5,19 @@ import { z } from "zod";
import { validateFields } from "@/middleware/middleware"; import { validateFields } from "@/middleware/middleware";
const router = express.Router(); const router = express.Router();
export default router.post("/", validateFields({ export default router.post(
"/",
validateFields({
id: z.number(), id: z.number(),
name: z.string(), name: z.string(),
model: z.string(), model: z.string(),
modelName: z.string(), modelName: z.string(),
vendorId: z.number().nullable(), vendorId: z.number().nullable(),
desc: z.string(), desc: z.string(),
}), async (req, res) => { }),
async (req, res) => {
const { id, name, model, modelName, vendorId, desc } = req.body; const { id, name, model, modelName, vendorId, desc } = req.body;
await u.db("o_agentDeploy").where({ id }).update({ id, name, model, modelName, vendorId, desc }); await u.db("o_agentDeploy").where({ id }).update({ id, name, model, modelName, vendorId, desc });
res.status(200).send(success("配置成功")); res.status(200).send(success("配置成功"));
}); },
);

View File

@ -76,7 +76,6 @@ export default router.post(
for await (const chunk of textStream) { for await (const chunk of textStream) {
fullResponse += chunk; fullResponse += chunk;
} }
console.log("%c Line:78 🥝 fullResponse", "background:#ea7e5c", fullResponse);
res.status(200).send(success(fullResponse)); res.status(200).send(success(fullResponse));
} else { } else {
const aiTypeFn = { const aiTypeFn = {

View File

@ -0,0 +1,115 @@
import express from "express";
import { serializeError } from "serialize-error";
import { success, error } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
import u from "@/utils";
import { z } from "zod";
import { transform } from "sucrase";
const router = express.Router();
const vendorConfigSchema = z.object({
id: z.string(),
author: z.string(),
description: z.string().optional(),
name: z.string(),
icon: z.string().optional(),
inputs: z.array(
z.object({
key: z.string(),
label: z.string(),
type: z.enum(["text", "password", "url"]),
required: z.boolean(),
placeholder: z.string().optional(),
}),
),
inputValues: z.record(z.string(), z.string()),
models: z.array(
z.discriminatedUnion("type", [
z.object({
name: z.string(),
modelName: z.string(),
type: z.literal("text"),
multimodal: z.boolean(),
tool: z.boolean(),
}),
z.object({
name: z.string(),
modelName: z.string(),
type: z.literal("image"),
mode: z.array(z.enum(["text", "singleImage", "multiReference"])),
}),
z.object({
name: z.string(),
modelName: z.string(),
type: z.literal("video"),
mode: z.array(
z.union([
z.enum([
"singleImage",
"multiImage",
"gridImage",
"startEndRequired",
"endFrameOptional",
"startFrameOptional",
"text",
"audioReference",
"videoReference",
]),
z.array(z.enum(["video", "image", "audio", "text"])),
]),
),
audio: z.union([z.literal("optional"), z.boolean()]),
durationResolutionMap: z.array(
z.object({
duration: z.array(z.number()),
resolution: z.array(z.string()),
}),
),
}),
]),
),
});
export default router.post(
"/",
validateFields({
id: z.string(),
tsCode: z.string(),
}),
async (req, res) => {
try {
const { tsCode, id } = req.body;
const jsCode = transform(tsCode, { transforms: ["typescript"] }).code;
const exports = u.vm(jsCode);
if (!exports) return res.status(400).send(success("脚本文件必须导出对象"));
if (!exports.textRequest) return res.status(400).send(success("脚本文件必须导出文本请求对象"));
if (!exports.imageRequest) return res.status(400).send(success("脚本文件必须导出图像请求对象"));
if (!exports.videoRequest) return res.status(400).send(success("脚本文件必须导出视频请求对象"));
if (!exports.vendor) return res.status(400).send(success("脚本文件必须导出vendor对象"));
const vendor = exports.vendor;
const result = vendorConfigSchema.safeParse(vendor);
if (!result.success) {
const errorMsg = result.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join("; ");
return res.status(400).send(error(`vendor配置校验失败: ${errorMsg}`));
}
await u
.db("o_vendorConfig")
.where("id", id)
.update({
author: vendor.author,
description: vendor.description || "",
name: vendor.name,
icon: vendor.icon || "",
inputs: JSON.stringify(vendor.inputs ?? []),
inputValues: JSON.stringify(vendor.inputValues ?? {}),
models: JSON.stringify(vendor.models ?? []),
code: tsCode,
createTime: Date.now(),
});
res.status(200).send(success(result.data));
} catch (err) {
console.log(err);
res.status(400).send(error(serializeError(err).message || "未知错误"));
}
},
);

View File

@ -158,14 +158,6 @@ export default router.post(
return code.slice(0, valueStart) + newValue + code.slice(valueEnd + 1); return code.slice(0, valueStart) + newValue + code.slice(valueEnd + 1);
}; };
// 替换 tsCode 中指定 key 的字符串/数字值(如 name: "xxx" 或 version: 1
const replacePrimitiveValue = (code: string, key: string, newValue: string | number): string => {
return code.replace(
new RegExp(`(\\b${key}\\s*:\\s*)(?:"[^"]*"|'[^']*'|\\d+)`),
(_, prefix) => `${prefix}${typeof newValue === "string" ? JSON.stringify(newValue) : newValue}`,
);
};
let updatedTsCode = tsCode; let updatedTsCode = tsCode;
updatedTsCode = replaceBlockValue(updatedTsCode, "inputs", JSON.stringify(inputs ?? vendor.inputs, null, 2)); updatedTsCode = replaceBlockValue(updatedTsCode, "inputs", JSON.stringify(inputs ?? vendor.inputs, null, 2));
updatedTsCode = replaceBlockValue(updatedTsCode, "inputValues", JSON.stringify(inputValues ?? vendor.inputValues, null, 2)); updatedTsCode = replaceBlockValue(updatedTsCode, "inputValues", JSON.stringify(inputValues ?? vendor.inputValues, null, 2));

View File

@ -1,4 +1,4 @@
// @db-hash e933f0aef750ba14e50c72aab5b6eeb7 // @db-hash 8e5f2b7a28d4494b291d802b055b6399
//该文件由脚本自动生成,请勿手动修改 //该文件由脚本自动生成,请勿手动修改
export interface memories { export interface memories {
@ -118,6 +118,11 @@ export interface o_project {
'videoModel'?: string | null; 'videoModel'?: string | null;
'videoRatio'?: string | null; 'videoRatio'?: string | null;
} }
export interface o_prompt {
'id'?: number;
'name'?: string | null;
'rompt'?: string | null;
}
export interface o_script { export interface o_script {
'content'?: string | null; 'content'?: string | null;
'createTime'?: number | null; 'createTime'?: number | null;
@ -236,6 +241,7 @@ export interface DB {
"o_outline": o_outline; "o_outline": o_outline;
"o_outlineNovel": o_outlineNovel; "o_outlineNovel": o_outlineNovel;
"o_project": o_project; "o_project": o_project;
"o_prompt": o_prompt;
"o_script": o_script; "o_script": o_script;
"o_scriptAssets": o_scriptAssets; "o_scriptAssets": o_scriptAssets;
"o_setting": o_setting; "o_setting": o_setting;

View File

@ -8,6 +8,7 @@ import getPath from "@/utils/getPath";
import vm from "@/utils/vm"; import vm from "@/utils/vm";
import task from "@/utils/taskRecord"; import task from "@/utils/taskRecord";
import Ai from "@/utils/ai"; import Ai from "@/utils/ai";
import { getPrompts } from "@/utils/getPrompts";
export default { export default {
db, db,
@ -20,4 +21,5 @@ export default {
getPath, getPath,
Ai, Ai,
task, task,
getPrompts,
}; };

View File

@ -26,21 +26,25 @@ class CleanNovel {
private async processChapter(novel: o_novel, intansce: ReturnType<typeof u.Ai.Text>): Promise<EventType | null> { private async processChapter(novel: o_novel, intansce: ReturnType<typeof u.Ai.Text>): Promise<EventType | null> {
try { try {
const skill = await useSkill("universal_agent.md"); const prompt = await u.getPrompts("event");
const resData = await intansce.invoke({ const resData = await intansce.invoke({
system: skill.prompt, system: prompt,
messages: [ messages: [
{ {
role: "user", role: "user",
content: "请根据以下小说章节生成事件摘要:\n" + novel.chapterData!, content:
"请根据以下小说章节数:" +
novel.chapterIndex +
"小说章节券:" +
novel.reel +
"小说章节名称:" +
novel.chapter +
"、小说章节内容生成事件摘要:\n" +
novel.chapterData!,
}, },
], ],
tools: skill.tools,
}); });
const preData = resData.text; const preData = resData.text;
this.emitter.emit("item", { id: novel.id, event: preData }); this.emitter.emit("item", { id: novel.id, event: preData });
return { id: novel.id!, event: preData }; return { id: novel.id!, event: preData };
} catch (e) { } catch (e) {
@ -71,10 +75,7 @@ class CleanNovel {
}; };
// 启动最多 concurrency 个并发任务 // 启动最多 concurrency 个并发任务
const workers = Array.from( const workers = Array.from({ length: Math.min(this.concurrency, allChapters.length) }, () => runNext());
{ length: Math.min(this.concurrency, allChapters.length) },
() => runNext()
);
await Promise.all(workers); await Promise.all(workers);

59
src/utils/getPrompts.ts Normal file
View File

@ -0,0 +1,59 @@
export async function getPrompts(type: string) {
if (type == "event") {
return `
#
##
1. **** \`|\` 开头、以 \`|\` 结尾,恰好 7 个字段
2. **** \`|\`**最后一个字符**必须是 \`|\`
3. \`|\` 之前不许有任何字符——没有引导语、没有解释、没有"根据……"、没有"以下是……"
4. \`|\` 之后不许有任何字符——没有总结、没有提取说明、没有改编建议
5. 线Markdown emoji
##
\`\`\`
| X章 {} | {} | {} | {线} | {} | {} | {} |
\`\`\`
###
| | | |
|------|----------|------|
| | \`第X章 {章节标题}\` | \`第1章 职业危机与许愿\` |
| | | \`林逸、白有容\` |
| | 30-60+ | \`林逸因解密风潮事业崩塌,颓废中许愿触发魔法系统绑定\` |
| 线 | **** \`强/中/弱3-8字理由\` | \`强(动机建立+系统激活)\` |
| | \`\` / \`\` / \`\` | \`\` |
| | **** \`X秒\`,禁止用分钟 | \`50秒\` |
| | \`+\` 连接,禁止星级/数字 | \`转折+悬疑\` |
**线**线///
****+45-6035-4525-35
****\`冲突\`\`恐怖\`\`情感\`\`转折\`\`高潮\`\`平铺\`\`喜剧\`\`悬疑\`\`情感崩溃\`
##
****
\`\`\`
| 1 | | "如果会魔法就好了" | + | | 50 | + |
\`\`\`
\`\`\`
| 12 | | | | | 25 | + |
\`\`\`
##
-
- 使
- 线
-
`;
}
}

2153
yarn.lock

File diff suppressed because it is too large Load Diff