diff --git a/backend/src/services/llmSchemas.ts b/backend/src/services/llmSchemas.ts index 8ca517f..dcefd22 100644 --- a/backend/src/services/llmSchemas.ts +++ b/backend/src/services/llmSchemas.ts @@ -93,18 +93,18 @@ export const cimReviewSchema = z.object({ }).describe("Management Team Overview section"), preliminaryInvestmentThesis: z.object({ - keyAttractions: z.string().describe("Key Attractions / Strengths (Why Invest?)"), - potentialRisks: z.string().describe("Potential Risks / Concerns (Why Not Invest?)"), - valueCreationLevers: z.string().describe("Initial Value Creation Levers (How PE Adds Value)"), + keyAttractions: z.string().describe("Key Attractions / Strengths (Why Invest?) — list each point on its own line, e.g. '1. Point one\\n2. Point two'"), + potentialRisks: z.string().describe("Potential Risks / Concerns (Why Not Invest?) — list each point on its own line, e.g. '1. Point one\\n2. Point two'"), + valueCreationLevers: z.string().describe("Initial Value Creation Levers (How PE Adds Value) — list each lever on its own line, e.g. '1. Lever one\\n2. Lever two'"), alignmentWithFundStrategy: z.string().describe("Alignment with Fund Strategy"), }).describe("Preliminary Investment Thesis section"), keyQuestionsNextSteps: z.object({ - criticalQuestions: z.string().describe("Critical Questions Arising from CIM Review"), - missingInformation: z.string().describe("Key Missing Information / Areas for Diligence Focus"), - preliminaryRecommendation: z.string().describe("Preliminary Recommendation"), + criticalQuestions: z.string().describe("Critical Questions Arising from CIM Review — list each question on its own line, e.g. '1. Question one\\n2. Question two'"), + missingInformation: z.string().describe("Key Missing Information / Areas for Diligence Focus — list each item on its own line"), + preliminaryRecommendation: z.string().describe("Preliminary Recommendation (Pass / Proceed with Caution / Proceed with Detailed Diligence)"), rationaleForRecommendation: z.string().describe("Rationale for Recommendation (Brief)"), - proposedNextSteps: z.string().describe("Proposed Next Steps"), + proposedNextSteps: z.string().describe("Proposed Next Steps — list each step on its own line, e.g. '1. Step one\\n2. Step two'"), }).describe("Key Questions & Next Steps section"), }); diff --git a/frontend/src/components/CIMReviewTemplate.tsx b/frontend/src/components/CIMReviewTemplate.tsx index cab5e87..beca75c 100644 --- a/frontend/src/components/CIMReviewTemplate.tsx +++ b/frontend/src/components/CIMReviewTemplate.tsx @@ -3,6 +3,23 @@ import Markdown from 'react-markdown'; import { Save, Download } from 'lucide-react'; import { cn } from '../utils/cn'; +/** + * Normalize inline numbered lists like "1) First item. 2) Second item." + * into proper markdown numbered lists for rendering. + * Also handles patterns like "1. First item 2. Second item" without line breaks. + */ +function normalizeToMarkdown(text: string): string { + if (!text) return text; + // Convert "N) " patterns (preceded by start-of-string or ". ") to markdown numbered list + // Match: start of string or after period+space, then digit(s) followed by ) and space + const result = text.replace(/(?:^|\.\s+)(\d+)\)\s/g, (_m, num, offset) => { + // If at start of string, just add newline before for markdown + if (offset === 0) return `${num}. `; + return `.\n\n${num}. `; + }); + return result; +} + interface CIMReviewData { // Deal Overview dealOverview: { @@ -343,8 +360,8 @@ const CIMReviewTemplate: React.FC = ({ {type === 'textarea' ? ( readOnly && value ? ( -
- {value} +
+ {normalizeToMarkdown(value)}
) : (