import type { IntentId } from '@/lib/interactive-demo/types' import { carnotCycleSimulator } from './carnot-cycle' import { carnotCycleAnim } from './carnot-cycle-anim' import { tsDiagramAnim } from './ts-diagram' import type { AnimPlugin, AnyPlugin, SimulatorPlugin } from './types' export const GENERIC_SIM_ID = 'generic-formula' as const const REGISTRY: Record = { [carnotCycleSimulator.id]: carnotCycleSimulator, [carnotCycleAnim.id]: carnotCycleAnim, [tsDiagramAnim.id]: tsDiagramAnim, } export function getPlugin(id: string): AnyPlugin | null { return REGISTRY[id] ?? null } export function getSimulator(id: string): SimulatorPlugin | null { const p = REGISTRY[id] return p?.family === 'sim' ? p : null } export function getAnimPlugin(id: string): AnimPlugin | null { const p = REGISTRY[id] return p?.family === 'anim' ? p : null } export function isCatalogSimId(id: string): boolean { return id !== GENERIC_SIM_ID && id in REGISTRY } export function listSimulators(): AnyPlugin[] { return Object.values(REGISTRY) } /** * Compact catalog injected into the section-generation prompt so the LLM * can pick a curated plugin (sim or anim) and bind note values into a preset. */ export function catalogForPrompt(lang: string): string { const fr = lang.startsWith('fr') const catalog = listSimulators().map((plugin) => ({ simId: plugin.id, family: plugin.family, summary: fr ? plugin.summary.fr : plugin.summary.en, keywords: plugin.keywords.slice(0, 10), ...(plugin.family === 'sim' ? { params: plugin.params.map((p) => ({ id: p.id, symbol: p.symbol, range: [p.min, p.max], default: p.defaultValue, unit: p.unit, })), outputs: plugin.outputs.map((o) => o.symbol), } : {}), })) return JSON.stringify(catalog, null, 1) } export type { SimulatorPlugin, AnimPlugin, AnyPlugin, AnimBeat, SimI18n, SimParamDef, SimOutputDef } from './types' export type { IntentId }