feat(agent): 添加视频创作工作流技能系统和流程工具

新增基于 SKILL.md 的视频创作工作流系统,Agent 可通过 skills 目录加载结构化的导演指令;实现 validate_storyboard、update_manifest_items、confirm_images 三个流程工具支撑分镜校验、提示词更新和图片确认。
This commit is contained in:
2026-05-08 01:54:04 +08:00
parent 3a124f0310
commit e16305840b
7 changed files with 316 additions and 13 deletions

View File

@@ -3,6 +3,9 @@ import type { AgentEvent } from '@earendil-works/pi-agent-core';
import { streamSimple } from '@earendil-works/pi-ai';
import type { AssistantMessage } from '@earendil-works/pi-ai';
import { WebSocket } from 'ws';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { createPiModel } from './pi-model';
import { createPiTools } from './pi-tools';
import { tools } from './tools/index';
@@ -10,6 +13,32 @@ import { videoAgent } from './index';
import { dbToPiMessages, saveUserMessage, saveAssistantMessage, saveToolResult, type DbMessage } from './pi-persist';
import { getDb } from '../db';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const SKILLS_DIR = path.join(__dirname, 'skills');
function loadSkills(): string {
const parts: string[] = [];
if (!fs.existsSync(SKILLS_DIR)) return '';
const skillDirs = fs.readdirSync(SKILLS_DIR, { withFileTypes: true })
.filter((d) => d.isDirectory());
for (const dir of skillDirs) {
const skillFile = path.join(SKILLS_DIR, dir.name, 'SKILL.md');
if (fs.existsSync(skillFile)) {
let content = fs.readFileSync(skillFile, 'utf-8');
// Strip YAML frontmatter
content = content.replace(/^---[\s\S]*?---\n*/, '');
parts.push(content.trim());
}
}
return parts.join('\n\n---\n\n');
}
const cachedSkillContent = loadSkills();
interface RunContext {
currentAssistantMsgId: string | null;
}
@@ -35,7 +64,7 @@ export async function runAgentChat(ws: WebSocket, convId: string, userContent: s
const agent = new Agent({
initialState: {
systemPrompt: videoAgent.getSystemPrompt(),
systemPrompt: videoAgent.getSystemPrompt() + (cachedSkillContent ? '\n\n' + cachedSkillContent : ''),
model,
thinkingLevel: 'off',
tools: piTools,