From 0fb07ab66aa565382d9ff234a8f334f96006e6da Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 05:56:33 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=93=B8=E6=B8=8A=E4=BB=A3=E7=90=86?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E5=B7=A5=E4=BD=9C=E6=B5=81=20=C2=B7=20?= =?UTF-8?q?=E5=A3=B3-=E6=A0=B8=E5=88=86=E7=A6=BB=E6=9E=B6=E6=9E=84=20(Core?= =?UTF-8?q?=20Brain=20+=20Agent)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新建 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> --- .github/brain/memory.json | 6 + .github/persona-brain/memory.json | 6 + .gitignore | 1 + .../backend/brain/agent-workflow.js | 756 ++++++++++++++++++ persona-studio/backend/routes/build.js | 95 ++- persona-studio/brain/evolution-log.json | 23 +- .../brain/memory/EXP-000/projects.json | 15 +- .../brain/memory/GUEST/projects.json | 32 + persona-studio/brain/pattern-library.json | 16 +- persona-studio/frontend/chat.js | 27 +- .../EXP-000/project-1773380616766/README.md | 8 - .../EXP-000/project-1773380616766/index.html | 14 - .../EXP-000/project-1773380616766/main.js | 1 - .../EXP-000/project-1773380616766/style.css | 1 - 14 files changed, 932 insertions(+), 69 deletions(-) create mode 100644 persona-studio/backend/brain/agent-workflow.js create mode 100644 persona-studio/brain/memory/GUEST/projects.json delete mode 100644 persona-studio/workspace/EXP-000/project-1773380616766/README.md delete mode 100644 persona-studio/workspace/EXP-000/project-1773380616766/index.html delete mode 100644 persona-studio/workspace/EXP-000/project-1773380616766/main.js delete mode 100644 persona-studio/workspace/EXP-000/project-1773380616766/style.css diff --git a/.github/brain/memory.json b/.github/brain/memory.json index d6645cda..cdc4885d 100644 --- a/.github/brain/memory.json +++ b/.github/brain/memory.json @@ -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", diff --git a/.github/persona-brain/memory.json b/.github/persona-brain/memory.json index 6cfa0e99..dae0f307 100644 --- a/.github/persona-brain/memory.json +++ b/.github/persona-brain/memory.json @@ -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", diff --git a/.gitignore b/.gitignore index 28f589d3..a0e218d9 100644 --- a/.gitignore +++ b/.gitignore @@ -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-* diff --git a/persona-studio/backend/brain/agent-workflow.js b/persona-studio/backend/brain/agent-workflow.js new file mode 100644 index 00000000..01766e25 --- /dev/null +++ b/persona-studio/backend/brain/agent-workflow.js @@ -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 API(OpenAI 兼容格式) + */ +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 [ + '', + '', + '', + ' ', + ' ', + ' ' + (plan.project_name || '项目') + '', + ' ', + '', + '', + '
', + '

🌊 ' + desc + '

', + '

由光湖 Persona Studio · 铸渊核心大脑 + 铸渊代理 协同开发

', + '

设计风格:' + designNotes + '

', + '
', + ' ', + '', + '' + ].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 +}; diff --git a/persona-studio/backend/routes/build.js b/persona-studio/backend/routes/build.js index a60dfb18..73a7d0a4 100644 --- a/persona-studio/backend/routes/build.js +++ b/persona-studio/backend/routes/build.js @@ -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,71 +48,94 @@ router.post('/start', async (req, res) => { }); } + // 防止 header injection:API 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 }); - // 记录项目 - memoryManager.addProject(dev_id, { - name: result.projectName || 'untitled', - email: email, - contact: safeContact, - status: 'completed', - created_at: new Date().toISOString(), - files: result.files || [] - }); + // 记录项目(GUEST 也记录,方便追踪) + try { + memoryManager.addProject(dev_id, { + name: result.projectName || 'untitled', + email: email, + contact: safeContact, + status: 'completed', + created_at: new Date().toISOString(), + files: result.files || [] + }); - // 自动提取知识 - memoryManager.autoExtractKnowledge(dev_id, conversation, result.projectName); + // 自动提取知识(仅注册开发者) + 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 }); } })(); diff --git a/persona-studio/brain/evolution-log.json b/persona-studio/brain/evolution-log.json index 6def2214..7d5a4016 100644 --- a/persona-studio/brain/evolution-log.json +++ b/persona-studio/brain/evolution-log.json @@ -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" } ] } \ No newline at end of file diff --git a/persona-studio/brain/memory/EXP-000/projects.json b/persona-studio/brain/memory/EXP-000/projects.json index 3c3e77f0..01804274 100644 --- a/persona-studio/brain/memory/EXP-000/projects.json +++ b/persona-studio/brain/memory/EXP-000/projects.json @@ -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" } \ No newline at end of file diff --git a/persona-studio/brain/memory/GUEST/projects.json b/persona-studio/brain/memory/GUEST/projects.json new file mode 100644 index 00000000..623b2b3b --- /dev/null +++ b/persona-studio/brain/memory/GUEST/projects.json @@ -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" +} \ No newline at end of file diff --git a/persona-studio/brain/pattern-library.json b/persona-studio/brain/pattern-library.json index 22c9d866..9889a7e9 100644 --- a/persona-studio/brain/pattern-library.json +++ b/persona-studio/brain/pattern-library.json @@ -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" } ] } \ No newline at end of file diff --git a/persona-studio/frontend/chat.js b/persona-studio/frontend/chat.js index 44bbb726..279c6135 100644 --- a/persona-studio/frontend/chat.js +++ b/persona-studio/frontend/chat.js @@ -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 ---- */ diff --git a/persona-studio/workspace/EXP-000/project-1773380616766/README.md b/persona-studio/workspace/EXP-000/project-1773380616766/README.md deleted file mode 100644 index d6977a59..00000000 --- a/persona-studio/workspace/EXP-000/project-1773380616766/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# project-1773380616766 - -## 需求描述 -Make a hello world page - -> 模板项目(AI 模型尚未配置,请管理员设置 MODEL_API_KEY) - -生成时间:2026-03-13T05:43:36.766Z \ No newline at end of file diff --git a/persona-studio/workspace/EXP-000/project-1773380616766/index.html b/persona-studio/workspace/EXP-000/project-1773380616766/index.html deleted file mode 100644 index 6fcb4630..00000000 --- a/persona-studio/workspace/EXP-000/project-1773380616766/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - project-1773380616766 - - - -

🌊 project-1773380616766

-

由光湖 Persona Studio 生成

- - - \ No newline at end of file diff --git a/persona-studio/workspace/EXP-000/project-1773380616766/main.js b/persona-studio/workspace/EXP-000/project-1773380616766/main.js deleted file mode 100644 index da7954e6..00000000 --- a/persona-studio/workspace/EXP-000/project-1773380616766/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log("Project initialized by Persona Studio"); diff --git a/persona-studio/workspace/EXP-000/project-1773380616766/style.css b/persona-studio/workspace/EXP-000/project-1773380616766/style.css deleted file mode 100644 index 2fd101aa..00000000 --- a/persona-studio/workspace/EXP-000/project-1773380616766/style.css +++ /dev/null @@ -1 +0,0 @@ -body { font-family: sans-serif; padding: 2rem; }