diff --git a/api/server/controllers/agents/v1.js b/api/server/controllers/agents/v1.js index 59a761aa70..b63bf091ac 100644 --- a/api/server/controllers/agents/v1.js +++ b/api/server/controllers/agents/v1.js @@ -1153,13 +1153,19 @@ const revertAgentVersionHandler = async (req, res) => { } } - if (updatedAgent.langfuse) { - const normalizedLangfuse = await normalizeLangfuseConfig(updatedAgent.langfuse, undefined, { + const revertVersion = existingAgent.versions?.[version_index]; + if (revertVersion?.langfuse) { + const normalizedLangfuse = await normalizeLangfuseConfig(revertVersion.langfuse, undefined, { preserveIncomingEncrypted: true, }); if (normalizedLangfuse) { revertUpdates.langfuse = normalizedLangfuse; } + } else if (existingAgent.langfuse) { + revertUpdates.$unset = { + ...(revertUpdates.$unset || {}), + langfuse: 1, + }; } if (Object.keys(revertUpdates).length > 0) { diff --git a/api/server/controllers/agents/v1.spec.js b/api/server/controllers/agents/v1.spec.js index 2dac7a3eaa..a325dbcbb5 100644 --- a/api/server/controllers/agents/v1.spec.js +++ b/api/server/controllers/agents/v1.spec.js @@ -1366,6 +1366,46 @@ describe('Agent Controllers - Mass Assignment Protection', () => { expect(agentInDb.langfuse.secretKey).not.toBe('sk-version'); expect(await decryptStoredSecret(agentInDb.langfuse.secretKey)).toBe('sk-version'); }); + + test('revertAgentVersionHandler should remove Langfuse when restored version lacks it', async () => { + const agentAuthorId = new mongoose.Types.ObjectId(); + const encryptedOriginal = await encryptStoredSecret('sk-original'); + const agent = await Agent.create({ + id: `agent_${uuidv4()}`, + name: 'Current Agent', + provider: 'openai', + model: 'gpt-4', + author: agentAuthorId, + langfuse: { + enabled: true, + publicKey: 'pk-current', + secretKey: encryptedOriginal, + baseUrl: 'https://cloud.langfuse.com', + }, + versions: [ + { + name: 'Historical Agent', + provider: 'openai', + model: 'gpt-4', + }, + ], + }); + + mockReq.user.id = agentAuthorId.toString(); + mockReq.params.id = agent.id; + mockReq.body = { version_index: 0 }; + + await revertAgentVersionHandler(mockReq, mockRes); + + expect(mockRes.json).toHaveBeenCalled(); + const updatedAgent = mockRes.json.mock.calls[0][0]; + expect(updatedAgent.langfuse).toBeUndefined(); + + const agentInDb = await Agent.findOne({ id: agent.id }).lean(); + expect(agentInDb.langfuse).toBeUndefined(); + const latestVersion = agentInDb.versions[agentInDb.versions.length - 1]; + expect(latestVersion.langfuse).toBeUndefined(); + }); }); describe('Mass Assignment Attack Scenarios', () => {