# Conflicts:
#	src/types/database.d.ts
This commit is contained in:
小帅 2026-03-24 10:23:50 +08:00
commit edc1c4cfbe
17 changed files with 293 additions and 125 deletions

View File

@ -29,6 +29,7 @@ description: >-
| 集数 | 总共拆分为几集 | 7集 |
| 单集时长 | 每集目标时长(分钟) | 2.5分钟 |
| 原著范围 | 改编覆盖的章节范围 | 第1-35章 |
| 章节ID列表 | 本次任务涉及的章节ID用于事件检索 | [1,2,3,4,5] |
| 平台规格 | 画面比例(竖屏/横屏) | 竖屏9:16 |
| 风格定位 | 短剧整体风格标签 | 诡异修仙+心理悬疑 |
| 付费策略 | 前几集免费、从第几集设付费点 | 前2集免费第3集起付费 |
@ -50,6 +51,7 @@ description: >-
- 集数:{totalEpisodes}集
- 单集时长:{episodeDuration}分钟(约{wordsPerEpisode}字台词)
- 原著范围:第{startChapter}-{endChapter}章
- 章节ID列表{chapterIds}
- 平台规格:{platform}
- 风格定位:{style}
- 付费策略:{paywall}
@ -72,24 +74,24 @@ description: >-
### 阶段1事件提取Event Extraction
- **触发词**提取事件、分析章节、事件列表、event
- **输入**原著小说章节文本
- **输入**章节ID列表由系统提示词中的章节映射表解析
- **输出**:结构化事件表(章节、角色、核心事件、主线关系、信息点数、预估时长、情绪强度)
- **派发指令模板**
```
你是执行层Agent请执行【事件提取】任务。
目标:从原著第{start}章到第{end}章提取结构化事件表。
目标:基于章节ID获取结构化事件表。
要求:
1. 调用 get_novel_text 获取原著文本
2. 按事件提取规范逐章分析
3. 输出标准事件表格式
4. 调用 set_planData_event 保存结果
1. 按系统提示词中的章节映射表确定章节ID数组 ids:number[]
2. 调用 get_novel_events 获取事件数据(传入 ids:number[]
3. 按事件提取规范整理为标准事件表格式
4. 将事件表作为后续阶段上下文返回(不写入 planData
```
### 阶段2故事骨架Story Skeleton
- **触发词**故事骨架、分集、三幕结构、skeleton
- **输入**:事件表(阶段1产出
- **输入**:事件表(通过 get_novel_events 获取
- **输出**:三幕结构 + 分集决策 + 全局删减记录 + 付费卡点设计
- **前置条件**:事件表已完成
- **派发指令模板**
@ -98,7 +100,7 @@ description: >-
你是执行层Agent请执行【故事骨架搭建】任务。
目标:基于已有事件表构建故事骨架。
要求:
1. 调用 get_planData 获取当前事件表
1. 调用 get_novel_events 获取当前任务章节的事件表(传入 ids:number[]
2. 设计三幕结构,明确每幕功能、核心问题、幕末转折
3. 制定分集决策({totalEpisodes}集×{episodeDuration}分钟),每集包含戏剧功能、核心场景、章节分配、删减决策、集末钩子、付费点
4. 记录全局删减决策
@ -108,7 +110,7 @@ description: >-
### 阶段3改编策略Adaptation Strategy
- **触发词**改编策略、改编决策、改编原则、adaptation
- **输入**:事件表 + 故事骨架(阶段1-2产出
- **输入**:事件表(通过 get_novel_events 获取) + 故事骨架阶段2产出
- **输出**:核心改编原则 + 删除决策 + 世界观呈现策略
- **前置条件**:故事骨架已完成
- **派发指令模板**
@ -117,7 +119,7 @@ description: >-
你是执行层Agent请执行【改编策略制定】任务。
目标:基于事件表和故事骨架制定改编策略。
要求:
1. 调用 get_planData 获取事件表和故事骨架
1. 调用 get_novel_events 获取事件表(传入 ids:number[]),并调用 get_planData 获取故事骨架
2. 确立核心改编原则(故事核优先、双线剪辑策略、恐怖克制原则)
3. 列出主要删除决策及理由
4. 制定世界观呈现策略
@ -127,8 +129,8 @@ description: >-
### 阶段4剧本编写Script Writing
- **触发词**写剧本、编剧、分镜脚本、script
- **输入**:事件表 + 故事骨架 + 改编策略阶段1-3产出
- **输出**:分集剧本(节拍结构 + 分镜脚本)
- **输入**:事件表(通过 get_novel_events 获取) + 故事骨架 + 改编策略阶段2-3产出
- **输出**:分集剧本(节拍结构 + 分镜脚本)并写入 SQLite
- **前置条件**:改编策略已完成
- **派发指令模板**
@ -137,13 +139,24 @@ description: >-
目标:编写第{ep}集剧本。
集信息:{从骨架获取的该集信息}
要求:
1. 调用 get_planData 获取全部工作区数据
1. 调用 get_novel_events 获取该集对应章节事件(传入 ids:number[]),并调用 get_planData 获取故事骨架与改编策略
2. 按节拍结构编写,严格控制总时长在{episodeDuration}分钟(约{wordsPerEpisode}字台词)
3. 每个节拍包含:场景描述、画面描述、台词、内心独白
4. 竖屏9:16格式注意画面构图适配
5. 调用 set_planData_script 保存结果
5. 仅在用户确认后调用 insert_script_to_sqlite 写入剧本SQL操作
```
### 阶段4额外安全规则SQL写入
`insert_script_to_sqlite` 为 SQL 写入操作,决策层必须先与用户明确对话确认,再允许执行层写入:
1. 先向用户展示待写入剧本摘要,并询问:`是否确认写入数据库?`
2. 仅当用户明确回复“确认/是/同意”后,才可派发写入指令
3. 派发剧本写入任务时,指令中必须包含:`用户已确认写入SQL: 是`
4. 若用户未确认或拒绝,禁止派发 SQL 写入
当用户要求删除剧本时,决策层必须提醒:`剧本删除请在道具本管理中手动删除`
## 调度规则
### 派发执行任务
@ -206,8 +219,10 @@ run_sub_agent(
1. **进度汇报**:每完成一个阶段,向用户汇报结果摘要和下一步计划
2. **审核结果展示**:将监督层的完整审核报告展示给用户,包括问题、建议和亮点
3. **等待用户决策**:审核发现问题时,**必须等待用户明确指示**后再执行修复,不可自行决定
4. **确认关键决策**:涉及大幅偏离既定策略的修改时,先咨询用户
5. **不暴露内部机制**:不向用户提及 Agent 名称、工具名称等实现细节
4. **SQL写入确认**:调用 `insert_script_to_sqlite` 前,必须完成用户明确确认
5. **删除请求提醒**:用户要求删除剧本时,提醒其在道具本管理中手动删除
6. **确认关键决策**:涉及大幅偏离既定策略的修改时,先咨询用户
7. **不暴露内部机制**:不向用户提及 Agent 名称、工具名称等实现细节
## 错误处理

View File

@ -18,17 +18,17 @@
### 阶段1事件提取
```
输入:原著小说文本第1-35章
处理:逐章提取结构化事件
输出:planData.eventMarkdown事件表
工具get_novel_text → set_planData_event
输入:章节ID数组 ids:number[](由系统提示词中的章节映射表提供
处理:调用事件检索工具并整理为标准事件表
输出:事件表Markdown作为后续阶段上下文不写入 planData
工具get_novel_events(ids:number[])
质量门章节覆盖率100%、角色名统一、强主线≥20章
```
### 阶段2故事骨架
```
输入:planData.event
输入:事件表(通过 get_novel_events(ids:number[]) 获取)
处理:三幕分割、按项目配置分集、删减决策、钩子设计
输出planData.storySkeleton
工具get_planData → set_planData_storySkeleton
@ -39,7 +39,7 @@
### 阶段3改编策略
```
输入:planData.event + planData.storySkeleton
输入:事件表get_novel_events + planData.storySkeleton
处理:提炼改编原则、确定删减依据、世界观呈现策略
输出planData.adaptationStrategy
工具get_planData → set_planData_adaptationStrategy
@ -50,12 +50,13 @@
### 阶段4剧本编写
```
输入:planData.event + planData.storySkeleton + planData.adaptationStrategy
输入:事件表get_novel_events + planData.storySkeleton + planData.adaptationStrategy
处理:按集编写(可并行或逐集)
输出:planData.script
工具get_planData + get_novel_text → set_planData_script
输出:SQLite 中的剧本记录
工具get_novel_events + get_planData + get_novel_text → insert_script_to_sqlite
质量门:时长合规、台词字数、画面可执行、资产一致
前置条件阶段3通过审核
附加前置条件:用户已明确确认写入 SQL
```
## 阶段间交互协议

View File

@ -3,20 +3,19 @@ name: execution
description: >-
短剧改编执行层Agent技能。负责接收决策层派发的具体任务并执行涵盖事件提取、
故事骨架搭建、改编策略制定、剧本编写四大任务类型。使用 get_novel_text 读取原著,
使用 get_planData 获取工作区状态,使用 set_planData 系列工具保存产出物。
使用 get_novel_events 获取章节事件数据,使用 get_planData 获取工作区状态,使用写入工具保存产出物。
当收到决策层的 run_sub_agent 调用时激活。
---
# 执行层 Agent 技能指令
你是短剧改编项目的**执行层 Agent**,只接收决策层派发的任务指令并执行。
你不与用户直接交互,所有产出物通过 `set_planData_*` 写入工作区
你不与用户直接交互,骨架与策略写入 planData剧本写入 SQLite
## 工作区数据结构
```typescript
const planData = {
event: string, // 章节事件表
storySkeleton: string, // 故事骨架
adaptationStrategy: string, // 改编策略
script: string, // 剧本内容
@ -24,7 +23,16 @@ const planData = {
```
- 读取:`get_planData` → 返回完整 planData 对象
- 写入:`set_planData_event` / `set_planData_storySkeleton` / `set_planData_adaptationStrategy` / `set_planData_script`
- 事件读取:`get_novel_events(ids:number[])` → 返回指定章节ID的事件数据
- 写入:`set_planData_storySkeleton` / `set_planData_adaptationStrategy` / `insert_script_to_sqlite`
### SQL写入安全约束剧本
`insert_script_to_sqlite` 属于 SQL 写入操作,执行前必须满足以下条件:
1. 决策层指令中明确包含:`用户已确认写入SQL: 是`
2. 若未包含该确认标记,执行层必须拒绝写入并返回:`缺少用户确认,未执行 SQL 写入`
3. 执行层不处理剧本删除请求;如收到删除诉求,返回提醒:`请在道具本管理中手动删除剧本`
## 项目背景
@ -52,8 +60,9 @@ const planData = {
**执行流程**
1. 调用 `get_novel_text` 获取指定章节范围的原著文本
2. 逐章分析,提取以下维度:
1. 根据决策层传入的章节ID构建 `ids:number[]`
2. 调用 `get_novel_events(ids:number[])` 获取结构化事件数据
3. 逐章分析,提取以下维度:
| 字段 | 说明 | 示例 |
|------|------|------|
@ -65,8 +74,8 @@ const planData = {
| 预估集长 | 秒数 | 45秒 |
| 情绪强度 | 情绪标签 | 冲突+恐怖 |
3. 生成汇总统计(总章节、强主线章节数、可压缩章节、预估总时长、目标时长、压缩比)
4. 调用 `set_planData_event` 保存 Markdown 表格格式的事件表
4. 生成汇总统计(总章节、强主线章节数、可压缩章节、预估总时长、目标时长、压缩比)
5. 输出 Markdown 表格格式的事件表,作为后续任务上下文(不写入 planData
**输出格式**:参考 [event-format.md](references/event-format.md)
@ -83,7 +92,7 @@ const planData = {
**执行流程**
1. 调用 `get_planData` 获取已有事件表
1. 调用 `get_novel_events(ids:number[])` 获取已有事件表
2. 确定故事核(一句话总结整部剧的核心吸引力)
3. 提炼隐线(人物弧:主角的内在成长轨迹)
4. 设计三幕结构:
@ -122,7 +131,7 @@ const planData = {
**执行流程**
1. 调用 `get_planData` 获取事件表和故事骨架
1. 调用 `get_novel_events(ids:number[])` 获取事件表,并调用 `get_planData` 获取故事骨架
2. 制定核心改编原则3-5条每条原则必须
- 明确优先级
- 给出正面指导("应该做什么")和负面边界("不应该做什么"
@ -152,7 +161,7 @@ const planData = {
**执行流程**
1. 调用 `get_planData` 获取全部工作区数据(事件表、骨架、改编策略)
1. 调用 `get_novel_events(ids:number[])` 获取事件表,并调用 `get_planData` 获取骨架与改编策略
2. 根据指定集数,从骨架中获取该集的:
- 覆盖章节范围
- 戏剧功能
@ -168,7 +177,7 @@ const planData = {
- 画面描述(构图、运镜、视觉重点)
- 台词/旁白/内心独白
- 表演指示(情绪、动作细节)
6. 调用 `set_planData_script` 保存
6. 仅当指令中包含 `用户已确认写入SQL: 是` 时,调用 `insert_script_to_sqlite` 写入剧本
**输出格式**:参考 [script-format.md](references/script-format.md)
@ -181,8 +190,9 @@ const planData = {
## 通用执行规范
1. **先读后写**:执行任何任务前,先调用 `get_planData` 了解当前工作区状态
1. **先读后写**:执行任何任务前,先调用 `get_planData` 了解工作区状态,并按需调用 `get_novel_events(ids:number[])` 获取事件数据
2. **增量更新**:如果工作区已有内容,在其基础上修改而非全部覆盖(除非指令明确要求重写)
3. **格式一致**:严格按照对应的输出格式规范,使用 Markdown 格式
4. **任务边界**:只执行指令中明确要求的任务,不越权执行其他阶段
5. **异常上报**:遇到无法处理的情况(如缺少前置数据),在返回结果中明确说明
5. **异常上报**:遇到无法处理的情况(如缺少前置数据),在返回结果中明确说明
6. **SQL安全执行**:未收到明确用户确认时,禁止调用 `insert_script_to_sqlite`

View File

@ -6,10 +6,12 @@ import ResTool from "@/socket/resTool";
export const deriveAssetSchema = z.object({
id: z.number().describe("衍生资产ID,如果新增则为空").optional(),
assetsId: z.string().describe("关联的资产ID"),
prompt: z.string().describe("生成提示词"),
name: z.string().describe("衍生资产名称"),
desc: z.string().describe("衍生资产描述"),
src: z.string().describe("衍生资产资源路径"),
state: z.enum(["未生成", "生成中", "已完成", "生成失败"]).describe("衍生资产生成状态"),
type: z.enum(["role", "tool", "scene", "clip"]).describe("衍生资产类型"),
});
export const assetItemSchema = z.object({
assetsId: z.string().describe("资产唯一标识"),

View File

@ -35,14 +35,30 @@ function buildSystemPrompt(skillPrompt: string, mem: Awaited<ReturnType<Memory["
const subAgentList = ["executionAI", "supervisionAI"] as const;
export async function decisionAI(ctx: AgentContext) {
const { isolationKey, text, abortSignal } = ctx;
const { isolationKey, text, abortSignal, resTool } = ctx;
resTool.systemMessage("决策层AI 接管聊天");
const memory = new Memory("scriptAgent", isolationKey);
await memory.add("user", text);
const [skill, mem] = await Promise.all([useSkill("script-agent", "decision"), memory.get(text)]);
const systemPrompt = buildSystemPrompt(skill.prompt, mem);
const prefixSystem = `请调用run_sub_agent完成任务`;
const projectData = await u.db("o_project").where("id", resTool.data.projectId).first();
const novelData = await u.db("o_novel").select("id", "chapterIndex as index");
const projectInfo = [
"## 项目信息",
`小说名称:${projectData?.name ?? "未知"}`,
`小说类型:${projectData?.type ?? "未知"}`,
`小说简介:${projectData?.intro ?? "无"}`,
`目标改编影视画风:${projectData?.artStyle ?? "无"}`,
`目标改编视频画幅:${projectData?.videoRatio ?? "16:9"}`,
].join("\n");
const prefixSystem = `${projectInfo}\n\n## 章节ID映射表\n${novelData.map((i: any) => `- ${i.id}: 第${i.index}`).join("\n")}\n\n`;
console.log("%c Line:57 🍧 prefixSystem", "background:#ea7e5c", prefixSystem);
const { textStream } = await u.Ai.Text("scriptAgent").stream({
system: prefixSystem + systemPrompt,
@ -92,7 +108,10 @@ export async function executionAI(ctx: AgentContext) {
}
export async function supervisionAI(ctx: AgentContext) {
const { isolationKey, text, abortSignal } = ctx;
const { isolationKey, text, abortSignal, resTool } = ctx;
resTool.systemMessage("监督层AI 接管聊天");
const memory = new Memory("scriptAgent", isolationKey);
const [skill, mem] = await Promise.all([useSkill("script-agent", "supervision"), memory.get(text)]);
@ -127,11 +146,10 @@ function runSubAgent(parentCtx: AgentContext) {
//运行子Agent
const subTextStream = await fn({ ...parentCtx, text: prompt });
let msg: ReturnType<typeof parentCtx.resTool.textMessage>;
let msg = parentCtx.resTool.textMessage();
let fullResponse = "";
for await (const chunk of subTextStream) {
if (!msg!) msg = parentCtx.resTool.textMessage();
msg.send(chunk);
fullResponse += chunk;
}

View File

@ -1,10 +1,21 @@
import { tool, Tool } from "ai";
import u from "@/utils";
import { z } from "zod";
import _ from "lodash";
import ResTool from "@/socket/resTool";
export const AssetSchema = z.object({
id: z.number().describe("衍生资产ID,如果新增则为空").optional(),
assetsId: z.string().describe("关联的资产ID"),
prompt: z.string().describe("生成提示词"),
name: z.string().describe("衍生资产名称"),
desc: z.string().describe("衍生资产描述"),
src: z.string().describe("衍生资产资源路径").optional(),
state: z.enum(["未生成", "生成中", "已完成", "生成失败"]).describe("衍生资产生成状态,新增默认未生成"),
type: z.enum(["role", "tool", "scene", "clip"]).describe("衍生资产类型"),
});
export const planData = z.object({
event: z.string().describe("章节事件"),
storySkeleton: z.string().describe("故事骨架"),
adaptationStrategy: z.string().describe("改编策略"),
script: z.string().describe("剧本内容"),
@ -20,6 +31,22 @@ const planDataKeyLabels = Object.fromEntries(
export default (resTool: ResTool, toolsNames?: string[]) => {
const { socket } = resTool;
const tools: Record<string, Tool> = {
get_novel_events: tool({
description: "获取章节事件",
inputSchema: z.object({
ids: z.array(z.number()).describe("章节id"),
}),
execute: async ({ ids }) => {
resTool.systemMessage(`正在阅读 章节事件 数据...`);
console.log("[tools] get_novel_events", ids);
const data = await u
.db("o_novel")
.select("id", "chapterIndex as index", "reel", "chapter", "chapterData", "event", "eventState")
.whereIn("id", ids);
const eventString = data.map((i: any) => [`${i.index}章,标题:${i.chapter},事件:${i.event}`].join("\n")).join("\n");
return eventString;
},
}),
get_planData: tool({
description: "获取工作区数据",
inputSchema: z.object({
@ -42,16 +69,6 @@ export default (resTool: ResTool, toolsNames?: string[]) => {
return "";
},
}),
set_planData_event: tool({
description: "保存章节事件到工作区",
inputSchema: z.object({ value: planData.shape.event }),
execute: async ({ value }) => {
console.log("[tools] set_planData event", value);
resTool.systemMessage("正在保存 章节事件 数据");
socket.emit("setPlanData", { key: "event", value });
return true;
},
}),
set_planData_storySkeleton: tool({
description: "保存故事骨架到工作区",
inputSchema: z.object({ value: planData.shape.storySkeleton }),
@ -72,13 +89,23 @@ export default (resTool: ResTool, toolsNames?: string[]) => {
return true;
},
}),
set_planData_script: tool({
description: "保存剧本内容到工作区",
inputSchema: z.object({ value: planData.shape.script }),
execute: async ({ value }) => {
console.log("[tools] set_planData script", value);
resTool.systemMessage("正在保存 剧本 数据");
socket.emit("setPlanData", { key: "script", value });
insert_script_to_sqlite: tool({
description: "将剧本内容插入sqlite数据库供后续业务使用",
inputSchema: z.object({
list: z.array(AssetSchema),
}),
execute: async ({ list }) => {
console.log("[tools] insert_script_to_sqlite", list);
await u.db("o_assets").insert(
list.map((i) => ({
name: i.name,
prompt: i.prompt,
type: i.type,
describe: i.desc,
projectId: resTool.data.projectId,
state: "未生成",
})),
);
return true;
},
}),

View File

@ -329,7 +329,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
},
//flowData-剧本
{
name: "o_flowData",
name: "o_agentWorkData",
builder: (table) => {
table.integer("id").notNullable();
table.integer("projectId");

View File

@ -1,4 +1,4 @@
// @routes-hash 61bac5fab20be7b63f8e2cda7f6945b6
// @routes-hash d482a1b197a774825d3bc1c4ca8b70c5
import { Express } from "express";
import route1 from "./routes/agents/clearMemory";
@ -61,24 +61,26 @@ import route57 from "./routes/script/delScript";
import route58 from "./routes/script/exportScript";
import route59 from "./routes/script/getScrptApi";
import route60 from "./routes/script/updateScript";
import route61 from "./routes/setting/agentDeploy/deployAgentModel";
import route62 from "./routes/setting/agentDeploy/getAgentDeploy";
import route63 from "./routes/setting/agentDeploy/updateKey";
import route64 from "./routes/setting/dbConfig/clearData";
import route65 from "./routes/setting/getTextModel";
import route66 from "./routes/setting/loginConfig/getUser";
import route67 from "./routes/setting/loginConfig/updateUserPwd";
import route68 from "./routes/setting/memoryConfig/getMemory";
import route69 from "./routes/setting/memoryConfig/sureMemory";
import route70 from "./routes/setting/vendorConfig/addVendor";
import route71 from "./routes/setting/vendorConfig/deleteVendor";
import route72 from "./routes/setting/vendorConfig/getVendorList";
import route73 from "./routes/setting/vendorConfig/modelTest";
import route74 from "./routes/setting/vendorConfig/updateVendor";
import route75 from "./routes/task/getTaskApi";
import route76 from "./routes/task/getTaskCategories";
import route77 from "./routes/task/taskDetails";
import route78 from "./routes/test/test";
import route61 from "./routes/scriptAgent/getPlanData";
import route62 from "./routes/scriptAgent/setPlanData";
import route63 from "./routes/setting/agentDeploy/deployAgentModel";
import route64 from "./routes/setting/agentDeploy/getAgentDeploy";
import route65 from "./routes/setting/agentDeploy/updateKey";
import route66 from "./routes/setting/dbConfig/clearData";
import route67 from "./routes/setting/getTextModel";
import route68 from "./routes/setting/loginConfig/getUser";
import route69 from "./routes/setting/loginConfig/updateUserPwd";
import route70 from "./routes/setting/memoryConfig/getMemory";
import route71 from "./routes/setting/memoryConfig/sureMemory";
import route72 from "./routes/setting/vendorConfig/addVendor";
import route73 from "./routes/setting/vendorConfig/deleteVendor";
import route74 from "./routes/setting/vendorConfig/getVendorList";
import route75 from "./routes/setting/vendorConfig/modelTest";
import route76 from "./routes/setting/vendorConfig/updateVendor";
import route77 from "./routes/task/getTaskApi";
import route78 from "./routes/task/getTaskCategories";
import route79 from "./routes/task/taskDetails";
import route80 from "./routes/test/test";
export default async (app: Express) => {
app.use("/api/agents/clearMemory", route1);
@ -141,22 +143,24 @@ export default async (app: Express) => {
app.use("/api/script/exportScript", route58);
app.use("/api/script/getScrptApi", route59);
app.use("/api/script/updateScript", route60);
app.use("/api/setting/agentDeploy/deployAgentModel", route61);
app.use("/api/setting/agentDeploy/getAgentDeploy", route62);
app.use("/api/setting/agentDeploy/updateKey", route63);
app.use("/api/setting/dbConfig/clearData", route64);
app.use("/api/setting/getTextModel", route65);
app.use("/api/setting/loginConfig/getUser", route66);
app.use("/api/setting/loginConfig/updateUserPwd", route67);
app.use("/api/setting/memoryConfig/getMemory", route68);
app.use("/api/setting/memoryConfig/sureMemory", route69);
app.use("/api/setting/vendorConfig/addVendor", route70);
app.use("/api/setting/vendorConfig/deleteVendor", route71);
app.use("/api/setting/vendorConfig/getVendorList", route72);
app.use("/api/setting/vendorConfig/modelTest", route73);
app.use("/api/setting/vendorConfig/updateVendor", route74);
app.use("/api/task/getTaskApi", route75);
app.use("/api/task/getTaskCategories", route76);
app.use("/api/task/taskDetails", route77);
app.use("/api/test/test", route78);
app.use("/api/scriptAgent/getPlanData", route61);
app.use("/api/scriptAgent/setPlanData", route62);
app.use("/api/setting/agentDeploy/deployAgentModel", route63);
app.use("/api/setting/agentDeploy/getAgentDeploy", route64);
app.use("/api/setting/agentDeploy/updateKey", route65);
app.use("/api/setting/dbConfig/clearData", route66);
app.use("/api/setting/getTextModel", route67);
app.use("/api/setting/loginConfig/getUser", route68);
app.use("/api/setting/loginConfig/updateUserPwd", route69);
app.use("/api/setting/memoryConfig/getMemory", route70);
app.use("/api/setting/memoryConfig/sureMemory", route71);
app.use("/api/setting/vendorConfig/addVendor", route72);
app.use("/api/setting/vendorConfig/deleteVendor", route73);
app.use("/api/setting/vendorConfig/getVendorList", route74);
app.use("/api/setting/vendorConfig/modelTest", route75);
app.use("/api/setting/vendorConfig/updateVendor", route76);
app.use("/api/task/getTaskApi", route77);
app.use("/api/task/getTaskCategories", route78);
app.use("/api/task/taskDetails", route79);
app.use("/api/test/test", route80);
}

View File

@ -14,7 +14,7 @@ export default router.post(
}),
async (req, res) => {
const { projectId, episodesId } = req.body;
const sqlData = await u.db("o_flowData").where({ projectId, episodesId }).first();
const sqlData = await u.db("o_agentWorkData").where({ projectId, episodesId }).first();
const scriptData = await u.db("o_script").where("projectId", projectId).first();

View File

@ -15,16 +15,16 @@ export default router.post(
}),
async (req, res) => {
const { projectId, episodesId } = req.body;
const sqlData = await u.db("o_flowData").where({ projectId, episodesId }).first();
const sqlData = await u.db("o_agentWorkData").where({ projectId, episodesId }).first();
if (!sqlData) {
await u.db("o_flowData").insert({
await u.db("o_agentWorkData").insert({
projectId,
episodesId,
data: JSON.stringify(req.body.data),
});
} else {
await u
.db("o_flowData")
.db("o_agentWorkData")
.where({ projectId, episodesId })
.update({
data: JSON.stringify(req.body.data),

View File

@ -22,15 +22,20 @@ export default router.post(
projectId,
createTime: Date.now(),
});
const assetsData = await u.db("o_assets").whereIn("id", assets).select();
const assetsIds = assetsData.map((item) => item.id);
const insertData = assetsIds.map((i) => {
return {
scriptId,
assetId: i,
};
});
await u.db("o_scriptAssets").insert(insertData);
if (assets.length) {
const assetsData = await u.db("o_assets").whereIn("id", assets).select();
if (assetsData.length) {
const assetsIds = assetsData.map((item) => item.id);
const insertData = assetsIds.map((i) => {
return {
scriptId,
assetId: i,
};
});
await u.db("o_scriptAssets").insert(insertData);
}
}
res.status(200).send(success({ message: "添加剧本成功" }));
},
);

View File

@ -20,15 +20,20 @@ export default router.post(
name,
content,
});
const assetsData = await u.db("o_assets").whereIn("id", assets).select();
await u.db("o_scriptAssets").where({ scriptId: id }).delete();
const insertData = assetsData.map((item) => {
return {
scriptId: id,
assetId: item.id,
};
});
await u.db("o_scriptAssets").insert(insertData);
if (assets.length) {
const assetsData = await u.db("o_assets").whereIn("id", assets).select();
await u.db("o_scriptAssets").where({ scriptId: id }).delete();
if (assetsData.length) {
const insertData = assetsData.map((item) => {
return {
scriptId: id,
assetId: item.id,
};
});
await u.db("o_scriptAssets").insert(insertData);
}
}
res.status(200).send(success({ message: "编辑剧本成功" }));
},
);

View File

@ -0,0 +1,36 @@
import express from "express";
import { success } from "@/lib/responseFormat";
import u from "@/utils";
import { z } from "zod";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
projectId: z.number(),
agentType: z.enum(["scriptAgent"]),
}),
async (req, res) => {
const { projectId, agentType } = req.body;
const data = await u.db("o_agentWorkData").where({ id: projectId, key: agentType }).first();
if (!data) {
await u.db("o_agentWorkData").insert({
id: projectId,
key: agentType,
data: JSON.stringify({
storySkeleton: "",
adaptationStrategy: "",
}),
});
return res.status(200).send(
success({
storySkeleton: "",
adaptationStrategy: "",
}),
);
}
res.status(200).send(success(JSON.parse(data.data ?? "{}")));
},
);

View File

@ -0,0 +1,28 @@
import express from "express";
import { success } from "@/lib/responseFormat";
import u from "@/utils";
import { z } from "zod";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
projectId: z.number(),
agentType: z.enum(["scriptAgent"]),
data: z.object({
storySkeleton: z.string(),
adaptationStrategy: z.string(),
}),
}),
async (req, res) => {
const { projectId, agentType, data } = req.body;
await u
.db("o_agentWorkData")
.where({ id: projectId, key: agentType })
.update({
data: JSON.stringify(data),
});
res.status(200).send(success());
},
);

View File

@ -2,7 +2,12 @@ import u from "@/utils";
import { Socket } from "socket.io";
class ResTool {
constructor(public socket: Socket) {}
public socket: Socket;
public data: Record<string, any>;
constructor(socket: Socket, data: Record<string, any> = {}) {
this.socket = socket;
this.data = data;
}
textMessage(name: string = "AI") {
const messageId = u.uuid();

View File

@ -35,7 +35,9 @@ export default (nsp: Namespace) => {
console.log("[scriptAgent] 已连接:", socket.id);
const resTool = new ResTool(socket);
const resTool = new ResTool(socket, {
projectId: socket.handshake.auth.projectId,
});
let abortController: AbortController | null = null;
socket.on("message", async (text: string) => {

View File

@ -1,4 +1,4 @@
// @db-hash 5c0247c298d78d118c90ddfde129e6e6
// @db-hash 5ea1f1cf9926d08390093d10da66e6ae
//该文件由脚本自动生成,请勿手动修改
export interface memories {
@ -22,6 +22,15 @@ export interface o_agentDeploy {
'name'?: string | null;
'vendorId'?: number | null;
}
export interface o_agentWorkData {
'createTime'?: number | null;
'data'?: string | null;
'espisodeId'?: number | null;
'id'?: number;
'key'?: string | null;
'projectId'?: number | null;
'updateTime'?: number | null;
}
export interface o_artStyle {
'id'?: number;
'name'?: string | null;
@ -195,6 +204,7 @@ export interface o_videoConfig {
export interface DB {
"memories": memories;
"o_agentDeploy": o_agentDeploy;
"o_agentWorkData": o_agentWorkData;
"o_artStyle": o_artStyle;
"o_assets": o_assets;
"o_assets2Storyboard": o_assets2Storyboard;