Alwrity version 0.5.4

This commit is contained in:
ajaysi
2025-08-11 10:54:50 +05:30
parent 13ca78f653
commit 39b96c44da
44 changed files with 10448 additions and 2119 deletions

View File

@@ -49,7 +49,8 @@ import {
School as SchoolIcon,
Lightbulb as LightbulbIcon,
Psychology as PsychologyIcon,
Timeline as TimelineIcon
Timeline as TimelineIcon,
FiberManualRecord as FiberManualRecordIcon
} from '@mui/icons-material';
import { motion, AnimatePresence } from 'framer-motion';
import { useEnhancedStrategyStore, STRATEGIC_INPUT_FIELDS } from '../../../stores/enhancedStrategyStore';
@@ -105,7 +106,8 @@ const ContentStrategyBuilder: React.FC = () => {
setError,
setCurrentStrategy,
setAIGenerating,
setSaving
setSaving,
personalizationData
} = useEnhancedStrategyStore();
const [showTooltip, setShowTooltip] = useState<string | null>(null);
@@ -117,6 +119,10 @@ const ContentStrategyBuilder: React.FC = () => {
const [refreshProgress, setRefreshProgress] = useState<number>(0);
const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
const [refreshError, setRefreshError] = useState<string | null>(null);
const [showEducationalModal, setShowEducationalModal] = useState(false);
const [educationalContent, setEducationalContent] = useState<any>(null);
const [generationProgress, setGenerationProgress] = useState<number>(0);
const [showAIRecModal, setShowAIRecModal] = useState(false);
// Ref to track if we've already set the default category
const hasSetDefaultCategory = useRef(false);
@@ -235,28 +241,9 @@ const ContentStrategyBuilder: React.FC = () => {
};
console.log('Attempting to create strategy with data:', strategyData);
const newStrategy = await createEnhancedStrategy(strategyData);
console.log('New strategy created:', newStrategy);
if (newStrategy && newStrategy.id) {
console.log('Generating AI recommendations for new strategy ID:', newStrategy.id);
await generateAIRecommendations(newStrategy.id);
// Set the current strategy and show success message
setCurrentStrategy(newStrategy);
setError(null); // Clear any previous errors
// Show success message
setTimeout(() => {
setError('Strategy created successfully! Check the Strategic Intelligence tab for detailed insights.');
}, 100);
// Auto-switch to Strategic Intelligence tab after creation
// This would need to be handled by the parent component
} else {
setError('Failed to create strategy or get strategy ID for AI generation.');
console.error('Failed to create strategy or get strategy ID for AI generation.');
}
// Use SSE streaming endpoint for strategy generation with educational content
await generateStrategyWithSSE(strategyData);
} else {
setError('Please fill in all required fields before generating AI insights.');
console.error('Form validation failed. Cannot generate AI insights.');
@@ -270,6 +257,224 @@ const ContentStrategyBuilder: React.FC = () => {
}
};
const generateStrategyWithSSE = async (strategyData: any) => {
try {
console.log('🚀 Starting SSE strategy generation...');
// Initialize progress and educational content
setGenerationProgress(0);
setEducationalContent({
title: '🤖 AI-Powered Strategy Generation',
description: 'Initializing AI analysis and preparing educational content...',
details: [
'🔧 Setting up AI services',
'📊 Loading user context',
'🎯 Preparing strategy framework',
'📚 Generating educational content'
],
insight: 'We\'re getting everything ready for your personalized AI strategy generation.',
estimated_time: '2-3 minutes total'
});
// Show educational modal
setShowEducationalModal(true);
// Create basic strategy first
const newStrategy = await createEnhancedStrategy(strategyData);
console.log('Basic strategy created:', newStrategy);
if (newStrategy && newStrategy.id) {
console.log('Starting AI generation for strategy ID:', newStrategy.id);
// Set a timeout for the entire process (5 minutes)
const processTimeout = setTimeout(async () => {
console.error('⏰ Strategy generation timeout after 5 minutes');
// Try to check if the strategy was actually created
try {
const existingStrategy = await contentPlanningApi.getEnhancedStrategy(newStrategy.id.toString());
if (existingStrategy) {
console.log('✅ Strategy was created successfully despite SSE timeout');
setCurrentStrategy(existingStrategy);
setError('Strategy created successfully! The AI generation may still be running in the background. Check the Strategic Intelligence tab for detailed insights.');
} else {
setError('Strategy generation is taking longer than expected. The process may still be running in the background. Please check the Strategic Intelligence tab for results.');
}
} catch (checkError) {
console.error('Error checking strategy status:', checkError);
setError('Strategy generation is taking longer than expected. The process may still be running in the background. Please check the Strategic Intelligence tab for results.');
}
setShowEducationalModal(false);
}, 5 * 60 * 1000); // 5 minutes
// Add heartbeat monitoring
let lastMessageTime = Date.now();
const heartbeatInterval = setInterval(() => {
const timeSinceLastMessage = Date.now() - lastMessageTime;
if (timeSinceLastMessage > 30000) { // 30 seconds without message
console.warn('⚠️ No SSE messages received for 30 seconds');
setEducationalContent({
title: '🤖 AI-Powered Strategy Generation',
description: 'AI analysis is still running in the background. This may take a few more minutes.',
details: [
'⏳ Processing complex AI analysis',
'📊 Analyzing market data',
'🎯 Generating strategic insights',
'📈 Calculating performance predictions'
],
insight: 'The AI is working on comprehensive analysis. This is normal for complex strategies.',
estimated_time: 'Additional 1-2 minutes'
});
}
}, 10000); // Check every 10 seconds
// Use SSE endpoint for AI generation with educational content
const eventSource = await contentPlanningApi.streamStrategyGeneration(Number(newStrategy.id));
console.log('🔌 SSE EventSource created:', eventSource);
console.log('🔌 SSE readyState:', eventSource.readyState);
// Handle SSE data with proper parsing
eventSource.onmessage = (event) => {
try {
console.log('📨 Raw SSE message:', event.data);
// Update last message time for heartbeat
lastMessageTime = Date.now();
// Parse the SSE data
const data = JSON.parse(event.data);
console.log('📨 Parsed SSE data:', data);
console.log('📨 Message type analysis:', {
hasStep: data.step !== undefined,
hasProgress: data.progress !== undefined,
hasEducationalContent: !!data.educational_content,
hasError: !!data.error,
hasSuccess: !!data.success,
hasType: !!data.type,
step: data.step,
progress: data.progress,
message: data.message
});
// Handle different types of messages
if (data.error) {
console.error('❌ SSE Error:', data.error);
clearTimeout(processTimeout);
clearInterval(heartbeatInterval);
setError(`AI generation failed: ${data.error}`);
setShowEducationalModal(false);
eventSource.close();
return;
}
// Handle step and progress updates (backend sends these)
if (data.step !== undefined) {
console.log('🔢 Updating step:', data.step);
// Calculate progress from step (each step is 10%)
const stepProgress = Math.min(data.step * 10, 100);
console.log('📊 Calculated progress from step:', stepProgress);
setGenerationProgress(stepProgress);
}
// Handle explicit progress updates
if (data.progress !== undefined) {
console.log('📊 Updating progress:', data.progress);
setGenerationProgress(data.progress);
}
// Handle educational content updates
if (data.educational_content) {
console.log('📚 Updating educational content:', data.educational_content);
setEducationalContent(data.educational_content);
}
// Handle completion
if (data.step === 10 && data.success) {
console.log('✅ Strategy generation completed successfully!');
clearTimeout(processTimeout);
clearInterval(heartbeatInterval);
setCurrentStrategy(data.strategy);
setShowEducationalModal(false);
setError('Strategy created successfully! Check the Strategic Intelligence tab for detailed insights.');
eventSource.close();
}
// Handle educational content from AI service manager
if (data.type === 'educational_content' && data.educational_content) {
console.log('📚 AI Service educational content:', data.educational_content);
setEducationalContent(data.educational_content);
}
// Handle success messages for individual steps
if (data.success && data.message) {
console.log('✅ Step completed:', data.message);
// Progress is already updated above, just log the success
}
} catch (parseError) {
console.error('❌ Error parsing SSE message:', parseError);
console.error('Raw message:', event.data);
}
};
// Handle SSE errors
eventSource.onerror = (error) => {
console.error('❌ SSE connection error:', error);
console.error(' ReadyState:', eventSource.readyState);
// Check connection state
switch (eventSource.readyState) {
case EventSource.CONNECTING:
console.log('🔄 SSE connection is connecting...');
break;
case EventSource.OPEN:
console.log('✅ SSE connection is open');
break;
case EventSource.CLOSED:
console.log('🔌 SSE connection is closed');
clearTimeout(processTimeout);
clearInterval(heartbeatInterval);
setError('Connection lost during AI generation. The process may still be running in the background. Please check the Strategic Intelligence tab for results.');
setShowEducationalModal(false);
break;
}
};
// Handle SSE connection open
eventSource.onopen = () => {
console.log('✅ SSE connection opened successfully');
console.log(' ReadyState:', eventSource.readyState);
console.log(' URL:', eventSource.url);
// Update educational content to show connection is established
setEducationalContent({
title: '🔌 Connection Established',
description: 'Successfully connected to AI generation service. Starting analysis...',
details: [
'✅ SSE connection active',
'🤖 AI service ready',
'📊 Data processing initialized',
'🎯 Strategy generation starting'
],
insight: 'The connection is now established and AI analysis is beginning.',
estimated_time: '2-3 minutes total'
});
};
} else {
setError('Failed to create strategy or get strategy ID for AI generation.');
console.error('Failed to create strategy or get strategy ID for AI generation.');
setShowEducationalModal(false);
}
} catch (error: any) {
console.error('Error in SSE strategy generation:', error);
setError(`Error in strategy generation: ${error.message || 'Unknown error'}`);
setShowEducationalModal(false);
}
};
const handleSaveStrategy = async () => {
try {
setSaving(true);
@@ -678,6 +883,7 @@ const ContentStrategyBuilder: React.FC = () => {
dataSource={dataSources[field.id]}
confidenceLevel={autoPopulatedFields[field.id] ? 0.8 : undefined}
dataQuality={autoPopulatedFields[field.id] ? 'High Quality' : undefined}
personalizationData={personalizationData[field.id]}
onChange={(value: any) => updateFormField(field.id, value)}
onValidate={() => validateFormField(field.id)}
onShowTooltip={() => setShowTooltip(field.id)}
@@ -784,26 +990,195 @@ const ContentStrategyBuilder: React.FC = () => {
{/* AI Recommendations Modal */}
<Dialog
open={showAIRecommendations}
onClose={() => setShowAIRecommendations(false)}
open={showAIRecModal}
onClose={() => setShowAIRecModal(false)}
maxWidth="md"
fullWidth
>
<DialogTitle>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<AutoAwesomeIcon />
AI Recommendations & Insights
<Box display="flex" alignItems="center" gap={1}>
<AutoAwesomeIcon color="primary" />
AI Recommendations
</Box>
</DialogTitle>
<DialogContent>
<AIRecommendationsPanel
aiGenerating={aiGenerating}
onGenerateRecommendations={handleCreateStrategy}
/>
<Typography variant="body1" gutterBottom>
AI recommendations are being generated for your strategy. This process may take a few minutes.
</Typography>
<LinearProgress variant="indeterminate" sx={{ mt: 2 }} />
</DialogContent>
</Dialog>
{/* Educational Modal for Strategy Generation */}
<Dialog
open={showEducationalModal}
onClose={() => setShowEducationalModal(false)}
maxWidth="lg"
fullWidth
>
<DialogTitle>
<Box display="flex" alignItems="center" gap={1}>
<SchoolIcon color="primary" />
{educationalContent?.title || 'AI Strategy Generation'}
</Box>
</DialogTitle>
<DialogContent>
{educationalContent ? (
<Box>
{/* Progress Bar */}
<Box sx={{ mb: 3 }}>
<Box display="flex" justifyContent="space-between" alignItems="center" mb={1}>
<Typography variant="body2" color="text.secondary">
Progress: {generationProgress}%
</Typography>
<Typography variant="body2" color="text.secondary">
Step {Math.ceil(generationProgress / 10)} of 10
</Typography>
</Box>
<LinearProgress
variant="determinate"
value={generationProgress}
sx={{ height: 8, borderRadius: 4 }}
/>
</Box>
{/* Educational Content */}
<Typography variant="h6" gutterBottom color="primary">
{educationalContent.title || 'AI Strategy Generation'}
</Typography>
{educationalContent.description && (
<Typography variant="body1" paragraph>
{educationalContent.description}
</Typography>
)}
{educationalContent.details && (
<Box sx={{ mb: 2 }}>
<Typography variant="subtitle2" gutterBottom>
What's happening:
</Typography>
<List dense>
{educationalContent.details.map((detail: string, index: number) => (
<ListItem key={index} sx={{ py: 0.5 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<FiberManualRecordIcon sx={{ fontSize: 8 }} />
</ListItemIcon>
<ListItemText primary={detail} />
</ListItem>
))}
</List>
</Box>
)}
{educationalContent.insight && (
<Box sx={{ mb: 2, p: 2, bgcolor: 'grey.50', borderRadius: 1 }}>
<Typography variant="subtitle2" color="primary" gutterBottom>
💡 Insight:
</Typography>
<Typography variant="body2">
{educationalContent.insight}
</Typography>
</Box>
)}
{educationalContent.ai_prompt_preview && (
<Box sx={{ mb: 2, p: 2, bgcolor: 'blue.50', borderRadius: 1 }}>
<Typography variant="subtitle2" color="primary" gutterBottom>
🤖 AI Prompt Preview:
</Typography>
<Typography variant="body2" fontFamily="monospace" fontSize="0.875rem">
{educationalContent.ai_prompt_preview}
</Typography>
</Box>
)}
{educationalContent.estimated_time && (
<Box sx={{ mb: 2, p: 2, bgcolor: 'orange.50', borderRadius: 1 }}>
<Typography variant="subtitle2" color="warning.main" gutterBottom>
⏱️ Estimated Time:
</Typography>
<Typography variant="body2">
{educationalContent.estimated_time}
</Typography>
</Box>
)}
{educationalContent.achievement && (
<Box sx={{ mb: 2, p: 2, bgcolor: 'green.50', borderRadius: 1 }}>
<Typography variant="subtitle2" color="success.main" gutterBottom>
✅ Achievement:
</Typography>
<Typography variant="body2">
{educationalContent.achievement}
</Typography>
</Box>
)}
{educationalContent.next_step && (
<Box sx={{ mb: 2, p: 2, bgcolor: 'purple.50', borderRadius: 1 }}>
<Typography variant="subtitle2" color="secondary.main" gutterBottom>
🔄 Next Step:
</Typography>
<Typography variant="body2">
{educationalContent.next_step}
</Typography>
</Box>
)}
{/* Summary for completion */}
{educationalContent.summary && (
<Box sx={{ mt: 3, p: 2, bgcolor: 'primary.50', borderRadius: 1 }}>
<Typography variant="h6" gutterBottom color="primary">
🎉 Strategy Generation Summary
</Typography>
<Grid container spacing={2}>
<Grid item xs={6}>
<Typography variant="body2">
<strong>Components:</strong> {educationalContent.summary.successful_components}/{educationalContent.summary.total_components}
</Typography>
</Grid>
<Grid item xs={6}>
<Typography variant="body2">
<strong>Content Pieces:</strong> {educationalContent.summary.total_content_pieces}
</Typography>
</Grid>
<Grid item xs={6}>
<Typography variant="body2">
<strong>Estimated ROI:</strong> {educationalContent.summary.estimated_roi}
</Typography>
</Grid>
<Grid item xs={6}>
<Typography variant="body2">
<strong>Timeline:</strong> {educationalContent.summary.implementation_timeline}
</Typography>
</Grid>
</Grid>
</Box>
)}
</Box>
) : (
/* Loading state when educational content is not yet available */
<Box sx={{ textAlign: 'center', py: 4 }}>
<CircularProgress sx={{ mb: 2 }} />
<Typography variant="h6" gutterBottom>
🤖 AI-Powered Strategy Generation
</Typography>
<Typography variant="body1" color="text.secondary" paragraph>
Initializing AI analysis and preparing educational content...
</Typography>
<Typography variant="body2" color="text.secondary">
This may take a few moments as we set up the AI services.
</Typography>
</Box>
)}
</DialogContent>
<DialogActions>
<Button onClick={() => setShowAIRecommendations(false)}>
Close
<Button
onClick={() => setShowEducationalModal(false)}
disabled={generationProgress < 100}
>
{generationProgress < 100 ? 'Please wait...' : 'Close'}
</Button>
</DialogActions>
</Dialog>

View File

@@ -15,7 +15,8 @@ import {
Alert,
Autocomplete,
InputAdornment,
Button
Button,
Collapse
} from '@mui/material';
import {
Help as HelpIcon,
@@ -23,7 +24,10 @@ import {
Warning as WarningIcon,
CheckCircle as CheckCircleIcon,
Edit as EditIcon,
Info as InfoIcon
Info as InfoIcon,
Person as PersonIcon,
ExpandMore as ExpandMoreIcon,
ExpandLess as ExpandLessIcon
} from '@mui/icons-material';
import { useEnhancedStrategyStore } from '../../../../stores/enhancedStrategyStore';
@@ -35,6 +39,22 @@ interface StrategicInputFieldProps {
dataSource?: string;
confidenceLevel?: number;
dataQuality?: string;
personalizationData?: {
explanation?: string;
data_sources?: {
website_analysis?: boolean;
audience_insights?: boolean;
ai_recommendations?: boolean;
research_config?: boolean;
};
personalization_factors?: {
website_url?: string;
industry_focus?: string;
writing_tone?: string;
expertise_level?: string;
business_size?: string;
};
};
onChange: (value: any) => void;
onValidate: () => boolean;
onShowTooltip: () => void;
@@ -80,6 +100,7 @@ const StrategicInputField: React.FC<StrategicInputFieldProps> = ({
dataSource,
confidenceLevel,
dataQuality,
personalizationData,
onChange,
onValidate,
onShowTooltip,
@@ -89,6 +110,7 @@ const StrategicInputField: React.FC<StrategicInputFieldProps> = ({
}) => {
const { getTooltipData } = useEnhancedStrategyStore();
const [isEditing, setIsEditing] = useState(false);
const [showPersonalization, setShowPersonalization] = useState(false);
const getAccent = (theme: any) => (theme?.palette?.[accentColorKey] ?? theme?.palette?.primary);
@@ -668,6 +690,94 @@ const StrategicInputField: React.FC<StrategicInputFieldProps> = ({
)}
</Box>
)}
{/* Personalization Information */}
{personalizationData && (
<Box sx={{
mt: 0.5,
p: 0.5,
bgcolor: 'rgba(76, 175, 80, 0.08)',
borderRadius: 1,
border: '1px solid rgba(76, 175, 80, 0.2)'
}}>
<Box sx={{
display: 'flex',
alignItems: 'center',
gap: 0.5,
cursor: 'pointer',
'&:hover': { bgcolor: 'rgba(76, 175, 80, 0.05)' },
borderRadius: 0.5,
p: 0.25
}}
onClick={() => setShowPersonalization(!showPersonalization)}
>
<PersonIcon sx={{ fontSize: 12, color: 'success.main' }} />
<Typography variant="caption" color="success.main" sx={{ fontSize: '0.6rem', fontWeight: 600 }}>
Personalized for your business
</Typography>
{showPersonalization ? (
<ExpandLessIcon sx={{ fontSize: 12, color: 'success.main' }} />
) : (
<ExpandMoreIcon sx={{ fontSize: 12, color: 'success.main' }} />
)}
</Box>
<Collapse in={showPersonalization}>
<Box sx={{ mt: 0.5, pl: 1.5 }}>
{/* Personalization Explanation */}
{personalizationData.explanation && (
<Typography variant="caption" color="text.secondary" sx={{ fontSize: '0.6rem', display: 'block', mb: 0.5 }}>
{personalizationData.explanation}
</Typography>
)}
{/* Personalization Factors */}
{personalizationData.personalization_factors && (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5, mb: 0.5 }}>
{Object.entries(personalizationData.personalization_factors).map(([key, value]) => (
value && (
<Chip
key={key}
label={`${key.replace(/_/g, ' ')}: ${value}`}
size="small"
variant="outlined"
color="success"
sx={{
fontSize: '0.5rem',
height: 16,
'& .MuiChip-label': { px: 0.5 }
}}
/>
)
))}
</Box>
)}
{/* Data Sources Used */}
{personalizationData.data_sources && (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
{Object.entries(personalizationData.data_sources).map(([source, used]) => (
used && (
<Chip
key={source}
label={source.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}
size="small"
variant="outlined"
color="info"
sx={{
fontSize: '0.5rem',
height: 16,
'& .MuiChip-label': { px: 0.5 }
}}
/>
)
))}
</Box>
)}
</Box>
</Collapse>
</Box>
)}
</Box>
{/* Error display */}

View File

@@ -547,6 +547,41 @@ class ContentPlanningAPI {
});
}
// SSE Strategy Generation
async streamStrategyGeneration(strategyId: number): Promise<EventSource> {
// The backend endpoint doesn't need strategy_id, it creates the strategy internally
const url = `${this.baseURL}/content-strategy/ai-generation/generate-comprehensive-strategy/stream?user_id=1&strategy_name=Enhanced%20Content%20Strategy`;
console.log('🚀 Creating SSE connection for strategy generation:');
console.log(' URL:', url);
console.log(' Base URL:', this.baseURL);
console.log(' Strategy ID:', strategyId);
const eventSource = new EventSource(url);
// Add comprehensive error handling
eventSource.onerror = (error) => {
console.error('❌ SSE Error in strategy generation:', error);
console.error(' ReadyState:', eventSource.readyState);
console.error(' URL:', url);
// Don't close immediately on error - let the frontend handle it
// eventSource.close();
};
eventSource.onopen = () => {
console.log('✅ SSE connection opened successfully');
console.log(' ReadyState:', eventSource.readyState);
console.log(' URL:', url);
};
eventSource.onmessage = (event) => {
console.log('📨 SSE message received:', event.data);
};
return eventSource;
}
async updateEnhancedStrategy(id: string, updates: any): Promise<any> {
return this.handleRequest(async () => {
const response = await apiClient.put(`${this.baseURL}/enhanced-strategies/${id}`, updates);

View File

@@ -159,6 +159,7 @@ interface EnhancedStrategyStore {
autoPopulatedFields: Record<string, any>;
dataSources: Record<string, string>;
inputDataPoints: Record<string, any>; // Detailed input data points from backend
personalizationData: Record<string, any>; // Personalization data for each field
// UI State
loading: boolean;
@@ -602,6 +603,7 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
autoPopulatedFields: {},
dataSources: {},
inputDataPoints: {}, // Initialize inputDataPoints
personalizationData: {}, // Initialize personalizationData
// UI State
loading: false,
@@ -722,6 +724,7 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
autoPopulatedFields: {},
dataSources: {},
inputDataPoints: {}, // Reset inputDataPoints
personalizationData: {}, // Reset personalizationData
currentStep: 0,
completedSteps: []
});
@@ -789,6 +792,7 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
// Transform the fields object to extract values for formData
const fieldValues: Record<string, any> = {};
const autoPopulatedFields: Record<string, any> = {};
const personalizationData: Record<string, any> = {};
Object.keys(fields).forEach(fieldId => {
const fieldData = fields[fieldId];
@@ -797,6 +801,13 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
if (fieldData && typeof fieldData === 'object' && 'value' in fieldData) {
fieldValues[fieldId] = fieldData.value;
autoPopulatedFields[fieldId] = fieldData.value;
// Extract personalization data if available
if (fieldData.personalization_data) {
personalizationData[fieldId] = fieldData.personalization_data;
console.log(`🎯 Personalization data for ${fieldId}:`, fieldData.personalization_data);
}
console.log(`✅ Auto-populated ${fieldId}:`, fieldData.value);
} else {
console.log(`❌ Skipping ${fieldId} - invalid data structure`);
@@ -805,11 +816,13 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
console.log('📝 Final field values:', fieldValues);
console.log('🔄 Final auto-populated fields:', autoPopulatedFields);
console.log('🎯 Personalization data:', personalizationData);
set((state) => ({
autoPopulatedFields,
dataSources: sources,
inputDataPoints, // Store the detailed input data points
personalizationData, // Store personalization data
formData: { ...state.formData, ...fieldValues }
}));