Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions apps/backend/app/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,14 @@ def _supports_temperature(provider: str, model: str) -> bool:
def _get_reasoning_effort(provider: str, model: str) -> str | None:
"""Return a default reasoning_effort for models that require it.

Some OpenAI gpt-5 models may return empty message.content unless a supported
`reasoning_effort` is explicitly set. This keeps downstream JSON parsing reliable.
Some OpenAI reasoning models (o1, o3, gpt-5) require a supported
`reasoning_effort` (low, medium, high) to work correctly.
"""
_ = provider
model_lower = model.lower()
if "gpt-5" in model_lower:
return "minimal"
# Handle GPT-5 (future-proofing) and o-series (o1, o3)
if any(m in model_lower for m in ["gpt-5", "o1", "o3"]):
return "medium"
return None


Expand Down
63 changes: 42 additions & 21 deletions apps/frontend/components/builder/resume-form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import React from 'react';
import React, { useEffect, useState } from 'react';
import {
DndContext,
closestCenter,
Expand Down Expand Up @@ -49,6 +49,11 @@ interface ResumeFormProps {

export const ResumeForm: React.FC<ResumeFormProps> = ({ resumeData, onUpdate }) => {
const { t } = useTranslations();
const [isMounted, setIsMounted] = useState(false);

useEffect(() => {
setIsMounted(true);
}, []);

// Get section metadata, falling back to defaults
const allSections = getSectionMeta(resumeData);
Expand Down Expand Up @@ -375,32 +380,48 @@ export const ResumeForm: React.FC<ResumeFormProps> = ({ resumeData, onUpdate })
);
};

const renderSectionList = (useDnd: boolean) => (
<div className="space-y-6 pb-20">
{sortedAllSections.map((section, index) => {
const isFirst = index === 0 || section.id === 'personalInfo';
const isLast = index === sortedAllSections.length - 1;
const isPersonalInfo = section.id === 'personalInfo';

const sectionContent = section.isDefault
? renderDefaultSection(section, isFirst, isLast)
: renderCustomSection(section, isFirst, isLast);

if (!useDnd) {
return (
<div key={section.id} className={isPersonalInfo ? '' : 'pl-4'}>
{sectionContent}
</div>
);
}

return (
<DraggableSectionWrapper key={section.id} id={section.id} disabled={isPersonalInfo}>
{sectionContent}
</DraggableSectionWrapper>
);
})}

{/* Add Section Button */}
<AddSectionButton onAdd={handleAddSection} />
</div>
);

if (!isMounted) {
return renderSectionList(false);
}

return (
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<SortableContext
items={sortedAllSections.map((s) => s.id)}
strategy={verticalListSortingStrategy}
>
<div className="space-y-6 pb-20">
{sortedAllSections.map((section, index) => {
const isFirst = index === 0 || section.id === 'personalInfo';
const isLast = index === sortedAllSections.length - 1;
const isPersonalInfo = section.id === 'personalInfo';

const sectionContent = section.isDefault
? renderDefaultSection(section, isFirst, isLast)
: renderCustomSection(section, isFirst, isLast);

return (
<DraggableSectionWrapper key={section.id} id={section.id} disabled={isPersonalInfo}>
{sectionContent}
</DraggableSectionWrapper>
);
})}

{/* Add Section Button */}
<AddSectionButton onAdd={handleAddSection} />
</div>
{renderSectionList(true)}
</SortableContext>
</DndContext>
);
Expand Down
4 changes: 2 additions & 2 deletions apps/frontend/lib/types/template-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ export interface TemplateSettings {
export const DEFAULT_TEMPLATE_SETTINGS: TemplateSettings = {
template: 'swiss-single',
pageSize: 'A4',
margins: { top: 10, bottom: 10, left: 10, right: 10 },
margins: { top: 5, bottom: 5, left: 10, right: 10 },
spacing: { section: 3, item: 2, lineHeight: 3 },
fontSize: { base: 3, headerScale: 3, headerFont: 'serif', bodyFont: 'sans-serif' },
compactMode: false,
compactMode: true,
showContactIcons: false,
accentColor: 'blue',
};
Expand Down