From 534da1121746b4192779b5a659c91fdd9be83525 Mon Sep 17 00:00:00 2001 From: KS Jannette Date: Fri, 13 Feb 2026 13:42:31 -0500 Subject: [PATCH] more --- backend/app.js | 2 +- backend/services/clustering.service.js | 13 +++++++++++-- backend/tests/Clustering.service.test.js | 16 +++++++++++----- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/backend/app.js b/backend/app.js index 451913e..7ba4b2b 100644 --- a/backend/app.js +++ b/backend/app.js @@ -11,6 +11,6 @@ app.use('/v1/notes', router); app.use((req, res) => { res.status(404).json({ error: `Requested path is invalid or does not exist: ${req.method} ${req.originalUrl}` }); - }); +}); export default app; diff --git a/backend/services/clustering.service.js b/backend/services/clustering.service.js index bd81d98..c7bd76a 100644 --- a/backend/services/clustering.service.js +++ b/backend/services/clustering.service.js @@ -40,6 +40,15 @@ export const clusterNotes = async (notes) => { ], }); - const raw = response.content[0].text; - return JSON.parse(raw); + const textBlock = response?.content?.[0]; + + if (!textBlock || textBlock.type !== 'text' || typeof textBlock.text !== 'string') { + throw new Error('Unexpected response from LLM API: no text content returned'); + } + + try { + return JSON.parse(textBlock.text); + } catch { + throw new Error('LLM API returned non-JSON response'); + } }; diff --git a/backend/tests/Clustering.service.test.js b/backend/tests/Clustering.service.test.js index 74a0596..711f6bf 100644 --- a/backend/tests/Clustering.service.test.js +++ b/backend/tests/Clustering.service.test.js @@ -35,7 +35,7 @@ describe('clusterNotes service', () => { it('should call Anthropic messages.create with the correct model', async () => { createMock.mockResolvedValue({ - content: [{ text: JSON.stringify(MOCK_CLUSTERS) }], + content: [{ type: 'text', text: JSON.stringify(MOCK_CLUSTERS) }], }); await clusterNotes(MOCK_NOTES); @@ -48,7 +48,7 @@ describe('clusterNotes service', () => { it('should include all note texts in prompt sent to the LLM API', async () => { createMock.mockResolvedValue({ - content: [{ text: JSON.stringify(MOCK_CLUSTERS) }], + content: [{ type: 'text', text: JSON.stringify(MOCK_CLUSTERS) }], }); await clusterNotes(MOCK_NOTES); @@ -62,7 +62,7 @@ describe('clusterNotes service', () => { it('should parse and return the clustered JSON from the API response', async () => { createMock.mockResolvedValue({ - content: [{ text: JSON.stringify(MOCK_CLUSTERS) }], + content: [{ type: 'text', text: JSON.stringify(MOCK_CLUSTERS) }], }); const result = await clusterNotes(MOCK_NOTES); @@ -72,10 +72,16 @@ describe('clusterNotes service', () => { it('should throw error when the API returns non-JSON', async () => { createMock.mockResolvedValue({ - content: [{ text: 'An unknown error occured when generting structured response.' }], + content: [{ type: 'text', text: 'An unknown error occured when generting structured response.' }], }); - await expect(clusterNotes(MOCK_NOTES)).rejects.toThrow(); + await expect(clusterNotes(MOCK_NOTES)).rejects.toThrow('non-JSON response'); + }); + + it('should throw error when the API response has no text content', async () => { + createMock.mockResolvedValue({ content: [] }); + + await expect(clusterNotes(MOCK_NOTES)).rejects.toThrow('no text content returned'); }); it('should throw error when Anthropic API authentication fails', async () => {