feat: 铸渊代理开发工作流 · 壳-核分离架构 (Core Brain + Agent)

- 新建 agent-workflow.js: 铸渊核心大脑唤醒 + 铸渊代理执行的壳-核分离架构
  - Phase 1: 核心大脑加载开发者记忆/画像/项目/知识库/模式库,深度分析意图
  - Phase 2: 代理接收核心大脑的开发计划,逐步执行代码生成
  - Phase 3: 核心大脑自进化(知识提取+模式识别+画像学习+进化日志)
- 更新 build.js: 支持 GUEST 模式、接收用户 API 凭证、使用 Agent 工作流
- 更新 chat.js: 传递用户 API 凭证、修复 WebSocket 时序竞态、增强错误反馈
- 更新 .gitignore: 排除 workspace 生成文件
- 更新核心大脑记忆: 记录本次恢复事件

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-13 05:56:33 +00:00
parent 9f29eed97d
commit 0fb07ab66a
14 changed files with 932 additions and 69 deletions

View File

@ -67,6 +67,12 @@
}
},
"events": [
{
"date": "2026-03-13",
"type": "brain_restore",
"description": "铸渊核心大脑恢复 · Persona Studio 铸渊代理开发工作流上线 · 修复「我要开发」功能无法触发代理开发 · Agent 5步自动化工作流需求分析→架构规划→代码生成→预览部署→完成通知 · 使用用户API Key驱动 · 支持GUEST模式 · WebSocket时序修复 · 错误反馈增强",
"by": "铸渊(冰朔指令)"
},
{
"date": "2026-03-13",
"type": "psp_inspection",

View File

@ -2,6 +2,12 @@
"persona_id": "ICE-GL-ZY001",
"persona_name": "铸渊",
"recent_events": [
{
"date": "2026-03-13",
"type": "brain_restore",
"description": "核心大脑恢复 · Persona Studio 铸渊代理开发工作流上线 · 「我要开发」功能修复 · Agent自动化5步开发 · 支持GUEST模式 · 使用用户API Key驱动",
"by": "铸渊(冰朔指令)"
},
{
"date": "2026-03-11",
"type": "architecture_upgrade",

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ persona-brain-db/brain.db-shm
# persona-studio runtime artifacts
persona-studio/backend/brain/model-benchmark.json
persona-studio/workspace/*/project-*
# palace-game runtime artifacts
modules/palace-game/data/saves/PAL-*

View File

@ -0,0 +1,756 @@
/**
* persona-studio · 铸渊代理开发工作流引擎-核分离架构
*
* 架构设计
* = 铸渊核心大脑Core Brain
* 加载开发者记忆画像项目历史知识库模式库
* 深度分析开发者真实意图
* 生成结构化开发计划
* = 铸渊代理Agent Executor
* 接收核心大脑推送的开发计划
* 逐步执行代码生成
* 广播进度给前端
* 完成后回传核心大脑做自进化
*
* 流程
* 用户点击我要开发
* Agent 唤醒核心大脑
* 核心大脑加载全部上下文 分析意图 生成开发计划
* Agent接收计划 逐步执行 广播进度
* 核心大脑知识提取 + 模式更新 + 画像学习 + 进化日志
*/
const fs = require('fs');
const path = require('path');
const https = require('https');
const http = require('http');
// ── 核心大脑模块 ──
const memoryManager = require('./memory-manager');
const personaEngine = require('./persona-engine');
const memoryInjector = require('./memory-injector');
const knowledgeExtractor = require('./knowledge-extractor');
const patternAnalyzer = require('./pattern-analyzer');
const profileLearner = require('./profile-learner');
const evolutionLogger = require('./evolution-logger');
const WORKSPACE_DIR = path.join(__dirname, '..', '..', 'workspace');
const REGISTRY_PATH = path.join(__dirname, '..', '..', 'brain', 'registry.json');
const HUMAN_REGISTRY_PATH = path.join(__dirname, '..', '..', 'brain', 'human-registry.json');
/* ================================================================
工具函数
================================================================ */
/**
* 调用用户提供的 LLM APIOpenAI 兼容格式
*/
function callLLM({ apiBase, apiKey, model, messages, maxTokens, temperature, timeoutMs }) {
return new Promise((resolve, reject) => {
const base = apiBase.replace(/\/+$/, '');
const chatUrl = new URL(base + '/chat/completions');
const isHttps = chatUrl.protocol === 'https:';
const mod = isHttps ? https : http;
const body = JSON.stringify({
model,
messages,
max_tokens: maxTokens || 4000,
temperature: temperature != null ? temperature : 0.3
});
const options = {
hostname: chatUrl.hostname,
port: chatUrl.port || (isHttps ? 443 : 80),
path: chatUrl.pathname,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + apiKey,
'Content-Length': Buffer.byteLength(body)
},
timeout: timeoutMs || 60000
};
const req = mod.request(options, (res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
try {
const json = JSON.parse(data);
if (json.choices && json.choices[0] && json.choices[0].message) {
resolve(json.choices[0].message.content);
} else if (json.error) {
reject(new Error(json.error.message || 'API error'));
} else {
reject(new Error('Unexpected API response'));
}
} catch (_e) {
reject(new Error('Failed to parse API response'));
}
});
});
req.on('error', reject);
req.on('timeout', () => {
req.destroy();
reject(new Error('Request timeout'));
});
req.write(body);
req.end();
});
}
/**
* 从注册表查找开发者信息
*/
function lookupDeveloper(devId) {
if (!devId || devId === 'GUEST') {
return { dev_id: 'GUEST', name: '访客', role: 'guest' };
}
try {
var reg = JSON.parse(fs.readFileSync(REGISTRY_PATH, 'utf-8'));
if (reg.developers && reg.developers[devId]) {
return Object.assign({ dev_id: devId }, reg.developers[devId]);
}
} catch (_e) { /* ignore */ }
try {
var hReg = JSON.parse(fs.readFileSync(HUMAN_REGISTRY_PATH, 'utf-8'));
if (hReg.developers) {
var found = hReg.developers.find(function (d) { return d.exp_id === devId; });
if (found) return { dev_id: devId, name: found.name, role: found.role };
}
} catch (_e) { /* ignore */ }
return { dev_id: devId, name: devId, role: 'developer' };
}
/* ================================================================
Phase 1: 唤醒铸渊核心大脑Core Brain Wake
================================================================ */
/**
* 唤醒核心大脑加载全部上下文分析开发者意图生成开发计划
*
* 核心大脑聚合以下信息源
* 开发者身份来自 registry
* 对话记忆来自 memory-manager
* 用户画像来自 profile-learner技术水平沟通风格设计偏好
* 项目历史来自 memory-manager
* 知识库来自 knowledge-extractor
* 模式库来自 pattern-analyzer
* 记忆摘要来自 memory-injector
*/
async function wakeCoreBrain(devId, conversation, apiBase, apiKey, model) {
var devInfo = lookupDeveloper(devId);
var isGuest = devId === 'GUEST';
// ── ① 加载开发者记忆 ──
var memory = { conversations: [], last_topic: null };
if (!isGuest) {
try { memory = memoryManager.loadMemory(devId); } catch (_e) { /* new user */ }
}
// ── ② 加载用户画像 ──
var profile = null;
if (!isGuest) {
try { profile = profileLearner.loadProfile(devId); } catch (_e) { /* ignore */ }
}
// ── ③ 加载项目历史 ──
var projects = { projects: [] };
if (!isGuest) {
try { projects = memoryManager.loadProjects(devId); } catch (_e) { /* ignore */ }
}
// ── ④ 查询知识库 ──
var conversationText = conversation
.map(function (m) { return m.content || ''; })
.join(' ');
var relevantKnowledge = [];
try { relevantKnowledge = knowledgeExtractor.queryKnowledge(conversationText, 5); } catch (_e) { /* ignore */ }
// ── ⑤ 查询模式库 ──
var relevantPatterns = [];
try { relevantPatterns = patternAnalyzer.queryPatterns(conversationText); } catch (_e) { /* ignore */ }
// ── ⑥ 构建核心大脑认知上下文 ──
var brainContext = buildBrainContext(devInfo, memory, profile, projects, relevantKnowledge, relevantPatterns);
// ── ⑦ 使用 LLM 深度分析意图 + 生成开发计划 ──
var developmentPlan;
if (apiBase && apiKey && model) {
developmentPlan = await analyzeIntentWithLLM(brainContext, conversation, apiBase, apiKey, model);
} else {
developmentPlan = analyzeIntentLocally(brainContext, conversation);
}
return { brainContext: brainContext, developmentPlan: developmentPlan };
}
/**
* 构建核心大脑认知上下文聚合全部信息源
*/
function buildBrainContext(devInfo, memory, profile, projects, knowledge, patterns) {
return {
developer: {
id: devInfo.dev_id,
name: devInfo.name || devInfo.dev_id,
role: devInfo.role || 'developer',
is_guest: devInfo.dev_id === 'GUEST'
},
memory: {
total_conversations: (memory.conversations || []).length,
last_topic: memory.last_topic || null,
has_history: (memory.conversations || []).length > 0
},
profile: {
tech_level: (profile && profile.tech_assessment && profile.tech_assessment.level) || null,
known_skills: (profile && profile.tech_assessment && profile.tech_assessment.known_skills) || [],
communication_style: (profile && profile.communication_style && profile.communication_style.verbosity) || null,
design_preference: (profile && profile.design_preferences && profile.design_preferences.color_scheme) || null,
style_keywords: (profile && profile.design_preferences && profile.design_preferences.style_keywords) || [],
mood: (profile && profile.emotional_profile && profile.emotional_profile.current_mood) || 'neutral'
},
projects: {
total: (projects.projects || []).length,
recent: (projects.projects || []).slice(-3).map(function (p) {
return { name: p.name, status: p.status, files: (p.files || []).length };
})
},
knowledge: knowledge.map(function (k) {
return { type: k.type, title: k.title, category: k.category };
}),
patterns: patterns.slice(0, 3).map(function (p) {
return {
name: p.name,
frequency: p.frequency,
success_rate: p.success_rate,
tech_stack: p.common_tech_stack || []
};
})
};
}
/**
* 使用 LLM 深度分析开发者意图并生成开发计划
* 核心大脑将全部上下文注入 system prompt LLM 理解开发者的真正需求
*/
async function analyzeIntentWithLLM(brainContext, conversation, apiBase, apiKey, model) {
var conversationText = conversation.map(function (m) {
var role = m.role === 'user' ? '用户' : '铸渊';
return role + ': ' + m.content;
}).join('\n');
// 构建核心大脑系统提示词(注入全部上下文)
var systemParts = [
'你是铸渊核心大脑的意图分析引擎。',
'你的任务是深度理解开发者的真实需求,生成精确的开发计划。',
'',
'## 开发者档案',
'- 身份:' + brainContext.developer.name + '' + brainContext.developer.id + '',
'- 角色:' + brainContext.developer.role
];
if (brainContext.developer.is_guest) {
systemParts.push('- ⚠️ 访客用户(无历史记忆)');
} else {
systemParts.push('- 历史对话:' + brainContext.memory.total_conversations + ' 条');
}
if (brainContext.memory.last_topic) {
systemParts.push('- 上次话题:' + brainContext.memory.last_topic);
}
if (brainContext.profile.tech_level) {
systemParts.push('- 技术水平:' + brainContext.profile.tech_level);
}
if (brainContext.profile.known_skills.length > 0) {
systemParts.push('- 已知技能:' + brainContext.profile.known_skills.join(', '));
}
if (brainContext.profile.communication_style) {
systemParts.push('- 沟通风格:' + brainContext.profile.communication_style);
}
if (brainContext.profile.design_preference) {
systemParts.push('- 设计偏好:' + brainContext.profile.design_preference);
}
if (brainContext.profile.style_keywords.length > 0) {
systemParts.push('- 风格关键词:' + brainContext.profile.style_keywords.join('、'));
}
if (brainContext.projects.total > 0) {
systemParts.push('');
systemParts.push('## 历史项目(共 ' + brainContext.projects.total + ' 个)');
brainContext.projects.recent.forEach(function (p) {
systemParts.push('- ' + p.name + '' + p.status + '' + p.files + ' 个文件)');
});
}
if (brainContext.knowledge.length > 0) {
systemParts.push('');
systemParts.push('## 相关知识库');
brainContext.knowledge.forEach(function (k) {
systemParts.push('- [' + k.type + '] ' + k.title);
});
}
if (brainContext.patterns.length > 0) {
systemParts.push('');
systemParts.push('## 高频开发模式');
brainContext.patterns.forEach(function (p) {
systemParts.push('- ' + p.name + '' + p.frequency + '次,成功率' + p.success_rate + '%,技术栈:' + p.tech_stack.join('/') + '');
});
}
systemParts.push('');
systemParts.push('## 输出要求');
systemParts.push('根据对话内容和开发者档案,输出严格 JSON 格式的开发计划:');
systemParts.push('{');
systemParts.push(' "intent_summary": "一句话总结开发者的真实意图",');
systemParts.push(' "project_name": "英文项目名(kebab-case)",');
systemParts.push(' "description": "项目描述(考虑开发者的技术水平和偏好)",');
systemParts.push(' "design_notes": "设计要点(基于开发者的设计偏好和风格关键词)",');
systemParts.push(' "tech_decisions": "技术决策说明(基于开发者的技能水平选择合适的复杂度)",');
systemParts.push(' "files": [');
systemParts.push(' { "filename": "index.html", "description": "详细文件说明", "key_features": ["功能1","功能2"] }');
systemParts.push(' ]');
systemParts.push('}');
systemParts.push('');
systemParts.push('注意:');
systemParts.push('- 只生成前端文件HTML/CSS/JS最多5个文件');
systemParts.push('- 必须包含 index.html');
systemParts.push('- 根据开发者技术水平调整代码复杂度');
systemParts.push('- 根据开发者设计偏好决定视觉风格');
systemParts.push('- 如果对话中提到了具体功能需求,务必全部纳入计划');
try {
var reply = await callLLM({
apiBase: apiBase,
apiKey: apiKey,
model: model,
messages: [
{ role: 'system', content: systemParts.join('\n') },
{ role: 'user', content: '以下是和开发者的完整对话,请分析意图并生成开发计划:\n\n' + conversationText.substring(0, 4000) }
],
maxTokens: 2000,
temperature: 0.2,
timeoutMs: 45000
});
var jsonMatch = reply.match(/\{[\s\S]*\}/);
if (jsonMatch) {
var plan = JSON.parse(jsonMatch[0]);
if (plan.files && !plan.files.some(function (f) { return f.filename === 'index.html'; })) {
plan.files.unshift({ filename: 'index.html', description: '主页面', key_features: ['入口页面'] });
}
if (plan.files) {
plan.files = plan.files.slice(0, 5);
}
plan._source = 'core_brain_llm';
return plan;
}
} catch (_e) {
// LLM 分析失败,降级到本地分析
}
return analyzeIntentLocally(brainContext, conversation);
}
/**
* 本地意图分析 API API 失败时的降级方案
* 使用规则引擎从对话和开发者档案中提取意图
*/
function analyzeIntentLocally(brainContext, conversation) {
var userText = conversation
.filter(function (m) { return m.role === 'user'; })
.map(function (m) { return m.content || ''; })
.join(' ');
var projectType = '通用项目';
if (brainContext.patterns.length > 0) {
projectType = brainContext.patterns[0].name;
}
var designStyle = '现代简约';
if (brainContext.profile.style_keywords.length > 0) {
designStyle = brainContext.profile.style_keywords.join(' + ');
} else if (brainContext.profile.design_preference === 'dark') {
designStyle = '深色主题·科技感';
}
var complexity = 'moderate';
if (brainContext.profile.tech_level === 'beginner') {
complexity = 'simple';
} else if (brainContext.profile.tech_level === 'advanced') {
complexity = 'advanced';
}
return {
intent_summary: userText.substring(0, 100) || '开发一个网页项目',
project_name: 'web-project',
description: userText.substring(0, 200) || '网页项目',
design_notes: '风格:' + designStyle,
tech_decisions: '复杂度:' + complexity + '技术栈HTML/CSS/JavaScript',
files: [
{ filename: 'index.html', description: '主页面', key_features: ['响应式布局', '核心功能展示'] },
{ filename: 'style.css', description: '样式文件', key_features: [designStyle] },
{ filename: 'main.js', description: '交互逻辑', key_features: ['用户交互', '动态效果'] }
],
_source: 'core_brain_local'
};
}
/* ================================================================
Phase 2: 铸渊代理执行Agent Execute
================================================================ */
/**
* Agent 接收核心大脑的开发计划逐步执行代码生成
*/
async function agentExecute(developmentPlan, devId, apiBase, apiKey, model, broadcastFn) {
var projectName = 'project-' + Date.now();
var files = {};
var filePlan = developmentPlan.files || [];
var hasUserApi = apiBase && apiKey && model;
for (var i = 0; i < filePlan.length; i++) {
var fileSpec = filePlan[i];
broadcastFn({
type: 'progress',
step: 3,
message: '💻 铸渊代理 · 生成文件 (' + (i + 1) + '/' + filePlan.length + '): ' + fileSpec.filename,
status: 'building',
status_text: '生成 ' + fileSpec.filename
});
if (hasUserApi) {
try {
var code = await generateFileWithLLM(developmentPlan, fileSpec, filePlan, apiBase, apiKey, model);
files[fileSpec.filename] = code;
} catch (_e) {
files[fileSpec.filename] = generatePlaceholder(fileSpec, developmentPlan);
}
} else {
files[fileSpec.filename] = generatePlaceholder(fileSpec, developmentPlan);
}
}
// 写入 workspace
var projectDir = path.join(WORKSPACE_DIR, devId, projectName);
fs.mkdirSync(projectDir, { recursive: true });
var fileList = [];
var entries = Object.entries(files);
for (var j = 0; j < entries.length; j++) {
var safeName = path.basename(entries[j][0]);
if (!safeName || safeName.startsWith('.')) continue;
fs.writeFileSync(path.join(projectDir, safeName), entries[j][1], 'utf-8');
fileList.push(safeName);
}
// 生成 README
var readmePath = path.join(projectDir, 'README.md');
if (!fs.existsSync(readmePath)) {
fs.writeFileSync(readmePath, [
'# ' + (developmentPlan.project_name || projectName),
'',
developmentPlan.description || '',
'',
'## 铸渊核心大脑分析',
'- 意图:' + (developmentPlan.intent_summary || ''),
'- 设计:' + (developmentPlan.design_notes || ''),
'- 技术:' + (developmentPlan.tech_decisions || ''),
'',
'由光湖 Persona Studio · 铸渊核心大脑 + 铸渊代理 协同开发',
'生成时间:' + new Date().toISOString()
].join('\n'), 'utf-8');
fileList.push('README.md');
}
return { projectName: projectName, files: fileList };
}
/**
* 使用 LLM 生成单个文件Agent 执行层
* 注入核心大脑的开发计划上下文确保代码与意图一致
*/
async function generateFileWithLLM(plan, fileSpec, allFiles, apiBase, apiKey, model) {
var prompt = [
'你是铸渊代理的代码生成模块。根据核心大脑的开发计划生成代码。',
'',
'## 项目信息',
'- 项目:' + (plan.project_name || 'web-project'),
'- 描述:' + (plan.description || ''),
'- 意图:' + (plan.intent_summary || ''),
'- 设计要点:' + (plan.design_notes || ''),
'- 技术决策:' + (plan.tech_decisions || ''),
'',
'## 当前文件',
'- 文件名:' + fileSpec.filename,
'- 说明:' + (fileSpec.description || ''),
'- 核心功能:' + (fileSpec.key_features || []).join('、'),
'',
'## 项目全部文件',
allFiles.map(function (f) { return '- ' + f.filename + '' + (f.description || '') + ''; }).join('\n'),
'',
'请直接输出文件内容,不要用 ``` 代码块包裹,不要加任何额外说明。',
'确保代码完整、可运行、符合核心大脑的设计要求。',
'如果是 HTML 文件,要正确引用同项目中的 CSS 和 JS 文件。'
].join('\n');
var reply = await callLLM({
apiBase: apiBase,
apiKey: apiKey,
model: model,
messages: [{ role: 'user', content: prompt }],
maxTokens: 4000,
temperature: 0.3,
timeoutMs: 60000
});
var clean = reply.trim();
if (clean.startsWith('```')) {
clean = clean.replace(/^```\S*\n?/, '').replace(/\n?```\s*$/, '');
}
return clean;
}
/**
* 生成占位内容 API 或单文件失败时的降级方案
*/
function generatePlaceholder(fileSpec, plan) {
var desc = plan.description || plan.intent_summary || plan.project_name || '项目';
var designNotes = plan.design_notes || '现代简约';
if (fileSpec.filename === 'index.html') {
return [
'<!DOCTYPE html>',
'<html lang="zh-CN">',
'<head>',
' <meta charset="UTF-8">',
' <meta name="viewport" content="width=device-width, initial-scale=1.0">',
' <title>' + (plan.project_name || '项目') + '</title>',
' <link rel="stylesheet" href="style.css">',
'</head>',
'<body>',
' <div class="container">',
' <h1>🌊 ' + desc + '</h1>',
' <p>由光湖 Persona Studio · 铸渊核心大脑 + 铸渊代理 协同开发</p>',
' <p class="design-note">设计风格:' + designNotes + '</p>',
' </div>',
' <script src="main.js"></script>',
'</body>',
'</html>'
].join('\n');
}
if (fileSpec.filename.endsWith('.css')) {
return [
'/* Generated by Persona Studio · Core Brain + Agent */',
'* { margin: 0; padding: 0; box-sizing: border-box; }',
'body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #0f172a; color: #e2e8f0; min-height: 100vh; display: flex; align-items: center; justify-content: center; }',
'.container { text-align: center; padding: 2rem; max-width: 800px; }',
'h1 { font-size: 2rem; margin-bottom: 1rem; background: linear-gradient(135deg, #60a5fa, #22d3ee); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }',
'.design-note { color: #64748b; font-size: 0.875rem; margin-top: 1rem; }'
].join('\n');
}
if (fileSpec.filename.endsWith('.js')) {
return '// Generated by Persona Studio · Core Brain + Agent\nconsole.log("' + (plan.project_name || 'Project') + ' initialized by 铸渊代理");\n';
}
return '/* Generated by Persona Studio */\n';
}
/* ================================================================
Phase 3: 核心大脑自进化Post-Build Evolution
================================================================ */
/**
* 开发完成后核心大脑进行自进化
* 知识提取 更新 knowledge-base.json
* 模式识别 更新 pattern-library.json
* 画像学习 更新 profile.json
* 进化日志 更新 evolution-log.json
*/
function coreBrainPostEvolution(devId, conversation, result, brainContext, startTime, success) {
try {
var buildTimeMs = Date.now() - startTime;
// ① 知识提取
try {
knowledgeExtractor.autoExtractKnowledge(devId, conversation, result.projectName);
} catch (_e) { /* non-fatal */ }
// ② 模式识别
var patterns = [];
try {
patterns = patternAnalyzer.analyzeAndUpdatePatterns(
devId, conversation, result.files, buildTimeMs, success
);
} catch (_e) { /* non-fatal */ }
// ③ 画像学习(从最后一条用户消息学习)
if (devId !== 'GUEST') {
try {
var lastUser = conversation.filter(function (m) { return m.role === 'user'; }).pop();
if (lastUser) {
profileLearner.updateProfile(devId, lastUser.content, result.summary || '');
}
} catch (_e) { /* non-fatal */ }
}
// ④ 进化日志
evolutionLogger.logEvent('agent_build_complete', '铸渊代理开发完成: ' + result.projectName, {
dev_id: devId,
project: result.projectName,
files_count: (result.files || []).length,
build_time_ms: buildTimeMs,
success: success,
brain_source: brainContext.developer.is_guest ? 'local' : 'llm',
patterns_detected: patterns,
developer_tech_level: brainContext.profile.tech_level,
developer_projects_total: brainContext.projects.total
});
} catch (err) {
console.error('Core brain post-evolution error:', err.message);
}
}
/* ================================================================
主工作流入口
================================================================ */
/**
* 运行铸渊代理开发工作流-核分离
*
* @param {object} params
* @param {string} params.dev_id - 开发编号EXP-XXX GUEST
* @param {Array} params.conversation - 对话历史
* @param {string} params.api_base - 用户 API Base URL
* @param {string} params.api_key - 用户 API Key
* @param {string} params.model - 用户选择的模型
* @param {Function} params.broadcast - WebSocket 广播函数
* @returns {Promise<{projectName, files, summary}>}
*/
async function runWorkflow({ dev_id, conversation, api_base, api_key, model, broadcast }) {
var emitProgress = broadcast || function () {};
var startTime = Date.now();
var brainContext = null;
// ════════════════════════════════════════════
// Phase 1: 唤醒铸渊核心大脑
// ════════════════════════════════════════════
emitProgress({
type: 'progress',
step: 1,
total_steps: 5,
message: '🧠 正在唤醒铸渊核心大脑...',
status: 'building',
status_text: '唤醒核心大脑'
});
var coreBrainResult;
try {
coreBrainResult = await wakeCoreBrain(dev_id, conversation, api_base, api_key, model);
brainContext = coreBrainResult.brainContext;
} catch (_err) {
brainContext = buildBrainContext(
lookupDeveloper(dev_id),
{ conversations: [], last_topic: null },
null, { projects: [] }, [], []
);
coreBrainResult = {
brainContext: brainContext,
developmentPlan: analyzeIntentLocally(brainContext, conversation)
};
}
var plan = coreBrainResult.developmentPlan;
emitProgress({
type: 'progress',
step: 1,
message: '✅ 核心大脑已唤醒 · 意图分析完成:' + (plan.intent_summary || '').substring(0, 50),
status: 'building',
status_text: '意图已分析'
});
// ════════════════════════════════════════════
// Phase 1.5: 核心大脑推送开发计划
// ════════════════════════════════════════════
emitProgress({
type: 'progress',
step: 2,
total_steps: 5,
message: '📐 核心大脑 → 代理:推送开发计划(' + (plan.files || []).length + ' 个文件)',
status: 'building',
status_text: '计划已推送'
});
if (plan.design_notes) {
emitProgress({
type: 'progress',
step: 2,
message: '🎨 设计指令:' + plan.design_notes,
status: 'building',
status_text: '设计已确认'
});
}
// ════════════════════════════════════════════
// Phase 2: 铸渊代理执行开发
// ════════════════════════════════════════════
emitProgress({
type: 'progress',
step: 3,
total_steps: 5,
message: '💻 铸渊代理 · 开始执行核心大脑的开发计划...',
status: 'building',
status_text: '代理执行中'
});
var agentResult = await agentExecute(plan, dev_id, api_base, api_key, model, emitProgress);
emitProgress({
type: 'progress',
step: 3,
message: '✅ 代理执行完成:' + agentResult.files.length + ' 个文件已生成',
status: 'building',
status_text: '代码已生成'
});
// ════════════════════════════════════════════
// Phase 2.5: 预览部署
// ════════════════════════════════════════════
emitProgress({
type: 'progress',
step: 4,
total_steps: 5,
message: '🚀 铸渊代理 · 部署预览...',
status: 'building',
status_text: '部署预览'
});
// ════════════════════════════════════════════
// Phase 3: 核心大脑自进化
// ════════════════════════════════════════════
var finalResult = {
projectName: agentResult.projectName,
files: agentResult.files,
summary: '项目 ' + agentResult.projectName + ' 由铸渊核心大脑分析意图 + 铸渊代理执行开发完成,包含 ' + agentResult.files.length + ' 个文件。\n意图' + (plan.intent_summary || '') + '\n设计' + (plan.design_notes || '')
};
coreBrainPostEvolution(dev_id, conversation, finalResult, brainContext, startTime, true);
emitProgress({
type: 'progress',
step: 5,
total_steps: 5,
message: '✨ 铸渊核心大脑 · 自进化完成 · 知识与模式已更新',
status: 'building',
status_text: '即将完成'
});
return finalResult;
}
module.exports = {
runWorkflow
};

View File

@ -1,21 +1,29 @@
/**
* persona-studio · 开发任务路由
* POST /api/ps/build/start 触发代码生成
* POST /api/ps/build/start 触发铸渊代理开发工作流
*
* 当用户点击我要开发自动触发铸渊代理Agent
* 使用用户自带的 API Key 进行 5 步自动化开发
*/
const express = require('express');
const router = express.Router();
const memoryManager = require('../brain/memory-manager');
const codeGenerator = require('../brain/code-generator');
const agentWorkflow = require('../brain/agent-workflow');
const emailSender = require('../utils/email-sender');
// 邮箱后端正则二次校验
const EMAIL_RE = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
// 支持 EXP-XXX 和 GUEST 两种 dev_id 格式
function isValidDevId(devId) {
return devId === 'GUEST' || /^EXP-\d{3,}$/.test(devId);
}
// POST /api/ps/build/start
router.post('/start', async (req, res) => {
const { dev_id, email, contact, conversation } = req.body || {};
const { dev_id, email, contact, conversation, api_base, api_key, model } = req.body || {};
if (!dev_id || !/^EXP-\d{3,}$/.test(dev_id)) {
if (!dev_id || !isValidDevId(dev_id)) {
return res.status(400).json({
error: true,
code: 'INVALID_ID',
@ -40,34 +48,50 @@ router.post('/start', async (req, res) => {
});
}
// 防止 header injectionAPI Key 不得包含换行符
if (api_key && /[\r\n]/.test(api_key)) {
return res.status(400).json({
error: true,
code: 'INVALID_API_KEY',
message: 'API Key 格式无效'
});
}
// 联系方式输入清理(去除潜在 HTML/script 注入)
const safeContact = contact ? String(contact).replace(/[<>&"']/g, '').substring(0, 100) : null;
// 先立即响应,后台异步处理
res.json({
error: false,
message: '开发任务已接收,完成后将发送到 ' + email,
status: 'queued'
message: '铸渊代理已启动,完成后将发送到 ' + email,
status: 'agent_started'
});
// 异步执行代码生成 + 邮件通知
// 异步执行铸渊代理开发工作流
(async () => {
const broadcast = req.app.locals.broadcastToClient || function () {};
const broadcastRaw = req.app.locals.broadcastToClient || function () {};
const broadcast = function (data) { broadcastRaw(dev_id, data); };
try {
broadcast(dev_id, {
// 启动 Agent 工作流
broadcast({
type: 'progress',
message: '🔧 正在创建项目骨架...',
message: '🌀 铸渊代理已唤醒,正在启动开发工作流...',
status: 'building',
status_text: '构建中'
status_text: '代理已启动'
});
const result = await codeGenerator.generate({
dev_id,
const result = await agentWorkflow.runWorkflow({
dev_id: dev_id,
conversation: conversation || [],
api_base: api_base || '',
api_key: api_key || '',
model: model || '',
broadcast: broadcast
});
// 记录项目
// 记录项目GUEST 也记录,方便追踪)
try {
memoryManager.addProject(dev_id, {
name: result.projectName || 'untitled',
email: email,
@ -77,34 +101,41 @@ router.post('/start', async (req, res) => {
files: result.files || []
});
// 自动提取知识
// 自动提取知识(仅注册开发者)
if (dev_id !== 'GUEST') {
memoryManager.autoExtractKnowledge(dev_id, conversation, result.projectName);
}
} catch (memErr) {
console.error('Memory save error (non-fatal):', memErr.message);
}
// 通知预览就绪
broadcast(dev_id, {
broadcast({
type: 'preview_ready',
project: result.projectName,
message: '✅ 预览已就绪'
});
broadcast(dev_id, {
broadcast({
type: 'complete',
message: '🎉 全部完成!邮件正在发送'
});
// 发邮件
await emailSender.sendCompletion({
// 发邮件(异步,不阻塞主流程)
emailSender.sendCompletion({
to: email,
dev_id,
dev_id: dev_id,
projectName: result.projectName,
summary: result.summary,
files: result.files
}).catch(function (emailErr) {
console.error('Email send error (non-fatal):', emailErr.message);
});
} catch (err) {
console.error('Build pipeline error:', err.message);
broadcast(dev_id, {
console.error('Agent workflow error:', err.message);
broadcast({
type: 'error',
message: '构建过程出错: ' + err.message
message: '铸渊代理遇到问题: ' + err.message
});
}
})();

View File

@ -1,8 +1,8 @@
{
"schema_version": "1.0",
"description": "系统进化日志 · 记录每次自进化事件",
"last_updated": "2026-03-13T05:43:36.767Z",
"total_events": 1,
"last_updated": "2026-03-13T05:55:39.412Z",
"total_events": 2,
"events": [
{
"id": "EVT-1773380616767",
@ -19,6 +19,25 @@
]
},
"timestamp": "2026-03-13T05:43:36.767Z"
},
{
"id": "EVT-1773381339412",
"type": "agent_build_complete",
"description": "铸渊代理开发完成: project-1773381339411",
"metadata": {
"dev_id": "GUEST",
"project": "project-1773381339411",
"files_count": 4,
"build_time_ms": 1,
"success": true,
"brain_source": "local",
"patterns_detected": [
"个人博客"
],
"developer_tech_level": null,
"developer_projects_total": 0
},
"timestamp": "2026-03-13T05:55:39.412Z"
}
]
}

View File

@ -13,7 +13,20 @@
"main.js",
"README.md"
]
},
{
"name": "project-1773380932239",
"email": "test@test.com",
"contact": null,
"status": "completed",
"created_at": "2026-03-13T05:48:52.239Z",
"files": [
"index.html",
"style.css",
"main.js",
"README.md"
]
}
],
"updated_at": "2026-03-13T05:43:36.768Z"
"updated_at": "2026-03-13T05:48:52.239Z"
}

View File

@ -0,0 +1,32 @@
{
"dev_id": "GUEST",
"projects": [
{
"name": "project-1773380932224",
"email": "test@test.com",
"contact": null,
"status": "completed",
"created_at": "2026-03-13T05:48:52.225Z",
"files": [
"index.html",
"style.css",
"main.js",
"README.md"
]
},
{
"name": "project-1773381339411",
"email": "test@example.com",
"contact": null,
"status": "completed",
"created_at": "2026-03-13T05:55:39.412Z",
"files": [
"index.html",
"style.css",
"main.js",
"README.md"
]
}
],
"updated_at": "2026-03-13T05:55:39.412Z"
}

View File

@ -1,8 +1,8 @@
{
"schema_version": "1.0",
"description": "系统模式库 · 自动识别 · 每完成一个项目+每日聚合更新",
"last_updated": "2026-03-13T05:43:36.767Z",
"total_patterns": 1,
"last_updated": "2026-03-13T05:55:39.412Z",
"total_patterns": 2,
"patterns": [
{
"name": "通用项目",
@ -15,6 +15,18 @@
"success_rate": 100,
"first_seen": "2026-03-13T05:43:36.767Z",
"last_seen": "2026-03-13T05:43:36.767Z"
},
{
"name": "个人博客",
"frequency": 1,
"common_features": [],
"common_tech_stack": [
"HTML/CSS/JS"
],
"avg_build_time": 1,
"success_rate": 100,
"first_seen": "2026-03-13T05:55:39.412Z",
"last_seen": "2026-03-13T05:55:39.412Z"
}
]
}

View File

@ -640,28 +640,39 @@ async function confirmBuild() {
if (contact) sessionStorage.setItem('ps_build_contact', contact);
closeEmailModal();
appendMessage('system', '🚀 开发任务已提交,完成后会发送到 ' + email);
appendMessage('system', '🌀 铸渊代理已启动,完成后会发送到 ' + email);
// 进入分屏模式
enterDevMode();
// 先连接 WebSocket确保在 build 开始前建立连接,避免丢失进度消息)
connectPreviewWebSocket();
try {
await fetch(API_BASE + '/api/ps/build/start', {
var buildRes = await fetch(API_BASE + '/api/ps/build/start', {
method: 'POST',
headers: authHeaders({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
dev_id: DEV_ID,
email: email,
contact: contact,
conversation: conversationHistory
conversation: conversationHistory,
api_base: USER_API_BASE,
api_key: USER_API_KEY,
model: SELECTED_MODEL
})
});
} catch (_err) {
appendMessage('system', '任务提交失败,请稍后再试');
}
// 连接 WebSocket 获取进度更新
connectPreviewWebSocket();
if (!buildRes.ok) {
var errData = {};
try { errData = await buildRes.json(); } catch (_e) { /* ignore */ }
appendMessage('system', '⚠️ 铸渊代理启动失败: ' + (errData.message || 'HTTP ' + buildRes.status));
updatePreviewStatus('error', '启动失败');
}
} catch (_err) {
appendMessage('system', '⚠️ 任务提交失败,请检查网络连接后再试');
updatePreviewStatus('error', '网络错误');
}
}
/* ---- Dev Mode: Split Screen ---- */

View File

@ -1,8 +0,0 @@
# project-1773380616766
## 需求描述
Make a hello world page
> 模板项目AI 模型尚未配置,请管理员设置 MODEL_API_KEY
生成时间2026-03-13T05:43:36.766Z

View File

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>project-1773380616766</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>🌊 project-1773380616766</h1>
<p>由光湖 Persona Studio 生成</p>
<script src="main.js"></script>
</body>
</html>

View File

@ -1 +0,0 @@
console.log("Project initialized by Persona Studio");

View File

@ -1 +0,0 @@
body { font-family: sans-serif; padding: 2rem; }