import { cache } from 'react'; import { unstable_cache } from 'next/cache'; import { AccountWithParams } from '@/packages/features/accounts/src/types/accounts'; import crypto from 'crypto'; import OpenAI from 'openai'; import PersonalCode from '~/lib/utils'; import { AnalysisTestResponse } from '../../(dashboard)/analysis-results/test/test-responses'; import { OrderAnalysisCard } from '../../_components/order-analyses-cards'; export const loadRecommendations = cache(recommendationsLoader); type FormattedAnalysisResponse = { value: string; name: string; responseTime: string; }; function canonical(v: unknown): string { return JSON.stringify(v, (_k, val) => { if (val && typeof val === 'object' && !Array.isArray(val)) { // sort object keys for stable JSON return Object.keys(val) .sort() .reduce((o: any, k) => ((o[k] = (val as any)[k]), o), {}); } return val; }); } const sha256 = (s: string) => crypto.createHash('sha256').update(s).digest('hex'); const getLatestResponseTime = (items: FormattedAnalysisResponse[]) => { if (!items?.length) return null; let latest = null; for (const it of items) { const d = new Date(it.responseTime); const t = d.getTime(); if (!Number.isNaN(t) && (latest === null || t > latest.getTime())) { latest = d; } } return latest; }; const getLatestUniqueAnalysResponses = ( analysisResponses: AnalysisTestResponse[], ): { name: string; value: string; responseTime: string }[] => { const analysisElements = analysisResponses .map(({ orderedAnalysisElements }) => orderedAnalysisElements) .flat(); console.log('analysisElements', analysisElements.length); const map = new Map(); for (const it of analysisElements) { const prev = map.get(it.analysisName); if (it.results.responseTime) { if ( !prev || new Date(it.results.responseTime) > new Date(prev.responseTime) ) { map.set(it.analysisName, { name: it.analysisName, value: it.results.responseValue, responseTime: it.results.responseTime, }); } } } return [...map.values()]; }; async function recommendationsLoader( analysisResponses: AnalysisTestResponse[], analyses: OrderAnalysisCard[], account: AccountWithParams | null, ): Promise { if (!account?.personal_code) { return []; } const client = new OpenAI(); const { gender } = PersonalCode.parsePersonalCode(account.personal_code); console.log('analysisResponses', analysisResponses); console.log('analyises', analyses); const latestUniqueAnalysResponses = getLatestUniqueAnalysResponses(analysisResponses); const latestResponseTime = getLatestResponseTime(latestUniqueAnalysResponses); const latestISO = latestResponseTime ? new Date(latestResponseTime).toISOString() : 'none'; console.log('latestResponseTime', latestResponseTime); const formattedAnalysisResponses = latestUniqueAnalysResponses.map( ({ name, value }) => ({ name, value }), ); const formattedAnalyses = analyses.map(({ description, title }) => ({ description, title, })); console.log('formattedAnalyses', JSON.stringify(formattedAnalyses)); console.log( 'latestUniqueAnalysResponses', JSON.stringify(latestUniqueAnalysResponses), ); const response = await client.responses.create({ model: 'gpt-5', store: false, prompt: { id: 'pmpt_68ca9c8bfa8c8193b27eadc6496c36440df449ece4f5a8dd', variables: { analyses: JSON.stringify(formattedAnalyses), results: JSON.stringify(formattedAnalysisResponses), gender: gender.value, }, }, }); const responseJson = JSON.parse(response.output_text); console.log('responseJson: ', responseJson); const keyPayload = { model: 'gpt-5', // swap to a model your project can access promptId: 'pmpt_68ca9c8bfa8c8193b27eadc6496c36440df449ece4f5a8dd', latestISO, }; const key = 'recs:' + sha256(canonical(keyPayload)); const run = unstable_cache(async () => { const response = await client.responses.create({ model: keyPayload.model, store: false, prompt: { id: keyPayload.promptId, variables: { analyses: JSON.stringify(formattedAnalyses), results: JSON.stringify(latestUniqueAnalysResponses), gender: gender.value, }, }, }); const json = JSON.parse(response.output_text); return json.recommended; }, ['recommendations', key]); return await run(); }