From 0ed020c3948396e69a535081cd887c93f7760fe9 Mon Sep 17 00:00:00 2001 From: yibo Date: Sun, 23 Aug 2026 15:34:47 +0800 Subject: [PATCH] fix(agents): 训练对话挂在 org-innovator 名下时,前端不再靠猜找链接 --- server/routes/company.js | 11 +++++++++-- web/src/views/CompanyDashboard.vue | 21 ++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/server/routes/company.js b/server/routes/company.js index 5f04402..cd25f0f 100644 --- a/server/routes/company.js +++ b/server/routes/company.js @@ -411,7 +411,12 @@ router.post('/:companyId/hire', async (req, res) => { }); // ── 核心逻辑扩展:自动补充定义 + 搜索注入 3 个初始 Skill + Innovator 训练 ── + // trainConversationId 提前算好(不等 setTimeout 里再算):训练对话实际挂在 + // org-innovator 名下(这条 fetch 打的是它),前端要能拼出正确链接直接跳过去, + // 就得在 res.json 之前拿到这个值 —— 放进 setTimeout 回调里再算,响应早发完了。 + let trainConversationId = null; if (result.status === 'training' || result.needsTraining) { + trainConversationId = `train-${req.params.companyId}-${role}-${Date.now().toString(36)}`; (async () => { try { console.log(`[Hire] 🚀 自动流水线启动: 为新员工 ${role} 安排 [定义 → 技能注入 → 训练]`); @@ -497,7 +502,7 @@ router.post('/:companyId/hire', async (req, res) => { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: `公司 ${req.params.companyId} 的员工 ${role} 骨架和基础技能已注入完毕。请你使用 FDE pipeline 对该 Agent ${namespacedId} (特别是它的技能)进行评测和进化训练,直到 Benchmark 达标 (Score ≥ 95)。训练过程包括 Hunt(验证数据), Digest, Evolver 等。请立即开始评估和训练,并保持向我汇报。`, - conversationId: `train-${req.params.companyId}-${role}-${Date.now().toString(36)}` + conversationId: trainConversationId }) }).catch(e => console.error('[Hire] Innovator 请求错误:', e.message)); }, 5000); @@ -519,7 +524,9 @@ router.post('/:companyId/hire', async (req, res) => { console.warn(`[Hire] ⚠️ 心跳挂载跳过: ${hbErr.message}`); } - res.json(result); + // trainConversationId 只在真的触发了训练时非空——前端凭它拼 + // `/agent/org-innovator/{trainConversationId}` 直达训练对话,不用再去猜挂在哪个 agent 下面。 + res.json({ ...result, trainConversationId }); } catch (err) { res.status(400).json({ error: err.message }); } diff --git a/web/src/views/CompanyDashboard.vue b/web/src/views/CompanyDashboard.vue index 54ec88b..9a8f983 100644 --- a/web/src/views/CompanyDashboard.vue +++ b/web/src/views/CompanyDashboard.vue @@ -930,18 +930,27 @@ async function submitHire() { hiring.value = true; try { const companyId = selectedCompany.value.id; + const trainConvIds = []; for (const roleId of selectedTemplates.value) { const tpl = templates.value.find(t => t.id === roleId); if (!tpl) continue; - await axios.post(`/api/company/${companyId}/hire`, { + const { data } = await axios.post(`/api/company/${companyId}/hire`, { role: roleId, type: tpl?.type, description: tpl?.description }); + if (data?.trainConversationId) trainConvIds.push(data.trainConversationId); } showHireModal.value = false; await loadCompanyStatus(companyId); await loadCompanyAgents(companyId); + if (trainConvIds.length > 0) { + // 训练对话挂在 org-innovator 名下,且要等 agent-creator 填完定义后才真正开始 + // (company.js /hire 里有 5 秒+delay),链接现在打开大概率是空的,所以不自动开新标签页, + // 只把正确地址交出来,用户过一会儿自己点。 + const links = trainConvIds.map(id => `${window.location.origin}/agent/org-innovator/${id}`).join('\n') + alert(`✅ 雇佣成功,已自动排队 Innovator 训练。\n训练对话稍后可在这里查看(挂在 org-innovator 名下,不是新员工自己):\n${links}`) + } } catch (e) { alert(`❌ 雇佣失败: ${e.response?.data?.error || e.message}`); } finally { @@ -1411,17 +1420,19 @@ ${trainInstructions.value} 3. 使用更新后的标准调用 Evolver 进行训练。完成全部 FDE 后向上级汇报最终结果。` // 发送请求,但不阻塞 UI - // org-innovator:27-naming §3.4 批次把 `innovator` 改名后这里没跟着改, - // 「重新训练」按钮从 2026-08-16 起一直静默 404(36 号文档阶段二实测发现)。 + const trainConvId = `train-${selectedCompany.value.id}-${agentId}-${Date.now().toString(36)}` axios.post(`/api/agent/org-innovator/chat`, { message, - conversationId: `train-${selectedCompany.value.id}-${agentId}-${Date.now().toString(36)}`, + conversationId: trainConvId, }).catch(e => { console.error('Retrain task error:', e) alert(`❌ 训练任务异常结束: ${e.message}`) }) - alert(`✅ 训练指令已发送给 Innovator,将开始在后台进行自动评估和重训 ${agentId}\n您可以在 Agent 的实时状态面板中观察进展。`) + // 训练对话实际挂在 org-innovator 名下(不是被训练的 agentId 自己), + // 直接开新标签页跳过去,别指望用户自己拼对 URL。 + window.open(`/agent/org-innovator/${trainConvId}`, '_blank') + alert(`✅ 训练指令已发送给 Innovator,将开始在后台进行自动评估和重训 ${agentId}\n训练对话已在新标签页打开(挂在 org-innovator 名下)。`) showTrainModal.value = false } catch (e) { alert(`❌ 发送训练指令失败: ${e.message}`) -- libgit2 0.21.4