Stage 3 & stage 4

This commit is contained in:
Desktop
2025-11-10 23:51:59 +05:00
parent 1bd9ebc974
commit 14beeed75c
7 changed files with 72 additions and 2259 deletions

View File

@@ -1,7 +1,6 @@
// Centralized API configuration and functions
// Auto-detect API URL based on current origin (supports both IP and subdomain access)
import { useAuthStore } from '../store/authStore';
import { useAIRequestLogsStore } from '../store/aiRequestLogsStore';
function getApiBaseUrl(): string {
// First check environment variables
@@ -575,43 +574,15 @@ export async function bulkUpdateClustersStatus(ids: number[], status: string): P
}
export async function autoClusterKeywords(keywordIds: number[], sectorId?: number): Promise<{ success: boolean; task_id?: string; clusters_created?: number; keywords_updated?: number; message?: string; error?: string }> {
const startTime = Date.now();
const addLog = useAIRequestLogsStore.getState().addLog;
const endpoint = `/v1/planner/keywords/auto_cluster/`;
const requestBody = { ids: keywordIds, sector_id: sectorId };
const pendingLogId = addLog({
function: 'autoClusterKeywords',
endpoint,
request: {
method: 'POST',
body: requestBody,
},
status: 'pending',
});
try {
const response = await fetchAPI(endpoint, {
method: 'POST',
body: JSON.stringify(requestBody),
});
const duration = Date.now() - startTime;
const updateLog = useAIRequestLogsStore.getState().updateLog;
// Update log with response data (including task_id for progress tracking)
if (pendingLogId && response) {
updateLog(pendingLogId, {
response: {
status: 200,
data: response,
},
status: response.success === false ? 'error' : 'success',
duration,
});
}
// Check if response indicates an error (success: false)
if (response && response.success === false) {
// Return error response as-is so caller can check result.success
@@ -620,108 +591,7 @@ export async function autoClusterKeywords(keywordIds: number[], sectorId?: numbe
return response;
} catch (error: any) {
const duration = Date.now() - startTime;
// Try to extract error response data if available
let errorResponseData = null;
let errorRequestSteps = null;
// Check if error has response data (from fetchAPI)
if (error.response || error.data) {
errorResponseData = error.response || error.data;
errorRequestSteps = errorResponseData?.request_steps;
} else if ((error as any).response) {
// Error object from fetchAPI has response attached
errorResponseData = (error as any).response;
errorRequestSteps = errorResponseData?.request_steps;
}
// Parse error message to extract error type
let errorType = 'UNKNOWN_ERROR';
let errorMessage = error.message || 'Unknown error';
// Check if error response contains JSON with error field
if (error.message && error.message.includes('API Error')) {
// Try to extract structured error from API response
const apiErrorMatch = error.message.match(/API Error \(\d+\): ([^-]+) - (.+)/);
if (apiErrorMatch) {
errorType = apiErrorMatch[1].trim();
errorMessage = apiErrorMatch[2].trim();
}
}
if (errorMessage.includes('OperationalError')) {
errorType = 'DATABASE_ERROR';
errorMessage = errorMessage.replace(/API Error \(\d+\): /, '').replace(/ - .*OperationalError.*/, ' - Database operation failed');
} else if (errorMessage.includes('ValidationError')) {
errorType = 'VALIDATION_ERROR';
} else if (errorMessage.includes('PermissionDenied')) {
errorType = 'PERMISSION_ERROR';
} else if (errorMessage.includes('NotFound')) {
errorType = 'NOT_FOUND_ERROR';
} else if (errorMessage.includes('IntegrityError')) {
errorType = 'DATABASE_ERROR';
} else if (errorMessage.includes('RelatedObjectDoesNotExist')) {
errorType = 'RELATED_OBJECT_ERROR';
// Extract clean error message
errorMessage = errorMessage.replace(/API Error \(\d+\): [^-]+ - /, '').trim();
}
// Update existing log or create new one
const updateLog = useAIRequestLogsStore.getState().updateLog;
const addRequestStep = useAIRequestLogsStore.getState().addRequestStep;
if (pendingLogId) {
updateLog(pendingLogId, {
response: {
status: errorResponseData?.status || 500,
error: errorMessage,
errorType,
data: errorResponseData,
},
status: 'error',
duration,
});
// Add request steps from error response if available
if (errorRequestSteps && Array.isArray(errorRequestSteps)) {
errorRequestSteps.forEach((step: any) => {
addRequestStep(pendingLogId, step);
});
}
} else {
// Create new log if pendingLogId doesn't exist
const errorLogId = addLog({
function: 'autoClusterKeywords',
endpoint,
request: {
method: 'POST',
body: requestBody,
},
response: {
status: errorResponseData?.status || 500,
error: errorMessage,
errorType,
data: errorResponseData,
},
status: 'error',
duration,
});
if (errorLogId && errorRequestSteps && Array.isArray(errorRequestSteps)) {
errorRequestSteps.forEach((step: any) => {
addRequestStep(errorLogId, step);
});
}
}
// Return error response in same format as successful response
// This allows the caller to check result.success === false
return {
success: false,
error: errorMessage,
errorType,
};
throw error;
}
}