apps/web/src/lib/eventFacts.server.ts

1import {
2	loadEventPageDocuments,
3	loadKnowledgeDocuments,
4} from '@local/ai/components/api/pineconeUpload'
5import {
6	type EventFactTopic,
7	publishedFactLinks,
8	selectEventFactAnswers,
9} from './eventFacts'
10
11/** Read-only exact FAQ lookup plus complete synced page bodies. No embeddings. */
12export async function loadEventFacts(
13	event: 'paris' | 'miami',
14	topic: EventFactTopic,
15) {
16	const scope = event === 'paris' ? 'event-world' : 'event-america'
17	const [general, local, allPages] = await Promise.all([
18		loadKnowledgeDocuments('general'),
19		loadKnowledgeDocuments(scope),
20		loadEventPageDocuments(event),
21	])
22	const eventSlug = `/events/unleash-${event}`
23	const pages = allPages
24		.filter(
25			(p) =>
26				p.slug.startsWith(`${eventSlug}/`) &&
27				(topic === 'volunteering'
28					? /volunteer/i.test(p.slug)
29					: topic === 'startupEligibility' ||
30							topic === 'startupAward' ||
31							topic === 'startupOptions' ||
32							topic === 'startupInclusions'
33						? /startup/i.test(p.slug)
34						: topic === 'parking'
35							? /\/plan-your-visit$/.test(p.slug)
36							: topic === 'openingHours'
37								? /\/agenda(?:-schedule)?$|\/plan-your-visit$/.test(p.slug)
38								: topic === 'exhibitorStandPlans'
39									? /exhibitor.manual/i.test(p.slug)
40									: topic === 'recordingAccess'
41										? /\/event-terms-and-conditions$/.test(p.slug)
42										: /\/attend(?:\/|$)|\/hr-professionals$/.test(p.slug)),
43		)
44		.map((p) => ({ title: p.title, url: p.slug, content: p.content }))
45	return {
46		event,
47		topic,
48		answers: [
49			...selectEventFactAnswers([...general, ...local], event, topic),
50			...(topic === 'refunds'
51				? selectEventFactAnswers([...general, ...local], event, 'ticketTransfers')
52				: []),
53		].map((answer) => ({
54			...answer,
55			answer: publishedFactLinks(
56				answer.answer,
57				allPages.map((page) => page.slug),
58			),
59		})),
60		pages,
61		contact:
62			topic === 'exhibitorStandPlans'
63				? 'customersuccess@unleash.ai'
64				: 'support@unleash.ai',
65		rules:
66			'Use only these source facts. Preserve conditional availability and application requirements. Do not invent roles, free-pass eligibility or onsite guarantees. A missing page does not mean the programme does not exist. Never substitute a sponsorship sales page for exhibitor logistics. Internal page links must be published; use the contact address when no public destination exists.',
67	}
68}
69