Implement V2 AI functions and enhance progress handling

- Added support for new V2 functions: `auto_cluster_v2` and `generate_ideas_v2`, including backend logic and API endpoints.
- Updated model configuration to ensure V2 functions validate the presence of models before execution.
- Enhanced progress modal to provide better feedback during asynchronous tasks, including task IDs for debugging.
- Updated frontend components to integrate new V2 functionalities and improve user experience with clustering and idea generation.
This commit is contained in:
Desktop
2025-11-10 22:16:02 +05:00
parent 46f5bb4d62
commit e2f2d79d4c
12 changed files with 920 additions and 58 deletions

View File

@@ -232,8 +232,10 @@ export function useProgressModal(): UseProgressModalReturn {
`/v1/system/settings/task_progress/${taskId}/`
);
// Helper function to start auto-increment progress (1% every 350ms until 80%)
// Only runs when no backend updates are coming (smooth fill-in animation)
// Helper function to start auto-increment progress
// 0-50%: 300ms per 1%
// 50-80%: 500ms per 1%
// If stuck at 80%: 1% per 500ms
const startAutoIncrement = () => {
// Clear any existing auto-increment interval
if (autoIncrementIntervalRef.current) {
@@ -241,11 +243,10 @@ export function useProgressModal(): UseProgressModalReturn {
autoIncrementIntervalRef.current = null;
}
// Only start if we're below 80% and status is processing
// Only start if we're below 100% and status is processing
const current = displayedPercentageRef.current;
if (current < 80) {
// Use a slightly longer interval to avoid conflicts with backend updates
autoIncrementIntervalRef.current = setInterval(() => {
if (current < 100) {
const doIncrement = () => {
setProgress(prev => {
// Check current status - stop if not processing
if (prev.status !== 'processing') {
@@ -257,17 +258,30 @@ export function useProgressModal(): UseProgressModalReturn {
}
const currentPercent = displayedPercentageRef.current;
// Only increment if still below 80%
if (currentPercent < 80) {
const newPercentage = Math.min(currentPercent + 1, 80);
let newPercentage = currentPercent;
let nextInterval = 300; // Default 300ms
if (currentPercent < 50) {
// 0-50%: 300ms per 1%
newPercentage = Math.min(currentPercent + 1, 50);
nextInterval = 300;
} else if (currentPercent < 80) {
// 50-80%: 500ms per 1%
newPercentage = Math.min(currentPercent + 1, 80);
nextInterval = 500;
} else if (currentPercent < 100) {
// Stuck at 80%+: 1% per 500ms
newPercentage = Math.min(currentPercent + 1, 99);
nextInterval = 500;
}
if (newPercentage > currentPercent && newPercentage < 100) {
displayedPercentageRef.current = newPercentage;
// Stop if we've reached 80%
if (newPercentage >= 80) {
if (autoIncrementIntervalRef.current) {
clearInterval(autoIncrementIntervalRef.current);
autoIncrementIntervalRef.current = null;
}
// Restart interval with new speed if needed
if (autoIncrementIntervalRef.current) {
clearInterval(autoIncrementIntervalRef.current);
autoIncrementIntervalRef.current = setInterval(doIncrement, nextInterval);
}
return {
@@ -275,7 +289,7 @@ export function useProgressModal(): UseProgressModalReturn {
percentage: newPercentage,
};
} else {
// Stop if we've reached 80%
// Stop if we've reached 100% or can't increment
if (autoIncrementIntervalRef.current) {
clearInterval(autoIncrementIntervalRef.current);
autoIncrementIntervalRef.current = null;
@@ -283,7 +297,11 @@ export function useProgressModal(): UseProgressModalReturn {
return prev;
}
});
}, 350); // Slightly longer interval to reduce conflicts
};
// Start with appropriate interval based on current percentage
const initialInterval = current < 50 ? 300 : 500;
autoIncrementIntervalRef.current = setInterval(doIncrement, initialInterval);
}
};
@@ -387,19 +405,20 @@ export function useProgressModal(): UseProgressModalReturn {
const safeTargetPercentage = Math.max(targetPercentage, currentDisplayedPercentage);
// Smooth progress animation: increment gradually until reaching target
// Use smaller increments and faster updates for smoother animation
// Speed: 300ms per 1% until 50%, then 500ms per 1%
if (safeTargetPercentage > currentDisplayedPercentage) {
// Start smooth animation
let animatedPercentage = currentDisplayedPercentage;
const animateProgress = () => {
if (animatedPercentage < safeTargetPercentage) {
// Calculate increment based on distance for smooth animation
const diff = safeTargetPercentage - animatedPercentage;
// Use smaller increments for smoother feel
// If close (< 5%), increment by 1, otherwise by 2
const increment = diff <= 5 ? 1 : Math.min(2, Math.ceil(diff / 10));
// Always increment by 1%
const increment = 1;
animatedPercentage = Math.min(animatedPercentage + increment, safeTargetPercentage);
displayedPercentageRef.current = animatedPercentage;
// Determine speed based on current percentage
const speed = animatedPercentage < 50 ? 300 : 500; // 300ms until 50%, then 500ms
setProgress({
percentage: animatedPercentage,
message: friendlyMessage,
@@ -414,13 +433,17 @@ export function useProgressModal(): UseProgressModalReturn {
});
if (animatedPercentage < safeTargetPercentage) {
// Smooth updates: 150ms for better UX
stepTransitionTimeoutRef.current = setTimeout(animateProgress, 150);
// Use appropriate speed based on current percentage
const nextSpeed = animatedPercentage < 50 ? 300 : 500;
stepTransitionTimeoutRef.current = setTimeout(animateProgress, nextSpeed);
} else {
stepTransitionTimeoutRef.current = null;
// After reaching target, start auto-increment if below 80% and no backend update pending
if (safeTargetPercentage < 80) {
startAutoIncrement();
} else if (safeTargetPercentage >= 80 && safeTargetPercentage < 100) {
// If at 80%+, start slow auto-increment (1% per 500ms)
startAutoIncrement();
}
}
}
@@ -435,7 +458,8 @@ export function useProgressModal(): UseProgressModalReturn {
} else {
// Same step or first step - start animation immediately
currentStepRef.current = currentStep;
animateProgress();
const initialSpeed = currentDisplayedPercentage < 50 ? 300 : 500;
stepTransitionTimeoutRef.current = setTimeout(animateProgress, initialSpeed);
}
} else {
// Target is same or less than current - just update message and details
@@ -455,6 +479,9 @@ export function useProgressModal(): UseProgressModalReturn {
// Start auto-increment if below 80% and no backend update
if (currentDisplayedPercentage < 80 && safeTargetPercentage === currentDisplayedPercentage) {
startAutoIncrement();
} else if (currentDisplayedPercentage >= 80 && currentDisplayedPercentage < 100) {
// If at 80%+, start slow auto-increment (1% per 500ms)
startAutoIncrement();
}
}
@@ -527,26 +554,61 @@ export function useProgressModal(): UseProgressModalReturn {
} else if (response.state === 'SUCCESS') {
const meta = response.meta || {};
// Clear any existing transition timeout
// Clear any existing transition timeout and auto-increment
if (stepTransitionTimeoutRef.current) {
clearTimeout(stepTransitionTimeoutRef.current);
stepTransitionTimeoutRef.current = null;
}
if (autoIncrementIntervalRef.current) {
clearInterval(autoIncrementIntervalRef.current);
autoIncrementIntervalRef.current = null;
}
// Get completion message with extracted values
const completionMessage = meta.message || '';
const allSteps = [...(meta.request_steps || []), ...(meta.response_steps || [])];
const stepInfo = getStepInfo('DONE', completionMessage, allSteps);
// Update to 100% with user-friendly completion message
currentStepRef.current = 'DONE';
displayedPercentageRef.current = 100;
setProgress({
percentage: 100,
message: stepInfo.friendlyMessage,
status: 'completed',
details: meta.details,
});
// Smooth completion animation: 5% per 500ms until 100%
const currentPercent = displayedPercentageRef.current;
if (currentPercent < 100) {
const animateToCompletion = () => {
const current = displayedPercentageRef.current;
if (current < 100) {
const increment = Math.min(5, 100 - current); // 5% per step, or remaining if less
const newPercentage = current + increment;
displayedPercentageRef.current = newPercentage;
setProgress({
percentage: newPercentage,
message: stepInfo.friendlyMessage,
status: 'completed',
details: meta.details,
});
if (newPercentage < 100) {
stepTransitionTimeoutRef.current = setTimeout(animateToCompletion, 500);
} else {
currentStepRef.current = 'DONE';
}
} else {
currentStepRef.current = 'DONE';
}
};
currentStepRef.current = 'DONE';
animateToCompletion();
} else {
// Already at 100%, just update message and status
currentStepRef.current = 'DONE';
displayedPercentageRef.current = 100;
setProgress({
percentage: 100,
message: stepInfo.friendlyMessage,
status: 'completed',
details: meta.details,
});
}
// Update final step logs
if (meta.request_steps || meta.response_steps) {