AI platform insights monitoring and website analysis monitoring services added

This commit is contained in:
ajaysi
2025-11-11 15:57:45 +05:30
parent d99c7c83a7
commit 7191c7e7f0
81 changed files with 10860 additions and 1567 deletions

View File

@@ -0,0 +1,86 @@
/**
* Platform Insights Monitoring API Client
* Provides typed functions for fetching platform insights (GSC/Bing) monitoring data.
*/
import { apiClient } from './client';
// TypeScript interfaces
export interface PlatformInsightsTask {
id: number;
platform: 'gsc' | 'bing';
site_url: string | null;
status: 'active' | 'failed' | 'paused';
last_check: string | null;
last_success: string | null;
last_failure: string | null;
failure_reason: string | null;
next_check: string | null;
created_at: string;
updated_at: string;
}
export interface PlatformInsightsStatusResponse {
success: boolean;
user_id: string;
gsc_tasks: PlatformInsightsTask[];
bing_tasks: PlatformInsightsTask[];
total_tasks: number;
}
export interface PlatformInsightsExecutionLog {
id: number;
task_id: number;
execution_date: string;
status: 'success' | 'failed' | 'running' | 'skipped';
result_data: any;
error_message: string | null;
execution_time_ms: number | null;
data_source: 'cached' | 'api' | 'onboarding' | 'storage' | null;
created_at: string;
}
export interface PlatformInsightsLogsResponse {
success: boolean;
logs: PlatformInsightsExecutionLog[];
total_count: number;
}
/**
* Get platform insights status for a user
*/
export const getPlatformInsightsStatus = async (
userId: string
): Promise<PlatformInsightsStatusResponse> => {
try {
const response = await apiClient.get(`/api/scheduler/platform-insights/status/${userId}`);
return response.data;
} catch (error: any) {
console.error('Error fetching platform insights status:', error);
throw new Error(error.response?.data?.detail || 'Failed to fetch platform insights status');
}
};
/**
* Get execution logs for platform insights tasks
*/
export const getPlatformInsightsLogs = async (
userId: string,
limit: number = 10,
taskId?: number
): Promise<PlatformInsightsLogsResponse> => {
try {
const params: any = { limit };
if (taskId) {
params.task_id = taskId;
}
const response = await apiClient.get(`/api/scheduler/platform-insights/logs/${userId}`, {
params
});
return response.data;
} catch (error: any) {
console.error('Error fetching platform insights logs:', error);
throw new Error(error.response?.data?.detail || 'Failed to fetch platform insights logs');
}
};

View File

@@ -9,8 +9,10 @@ import { apiClient } from './client';
export interface ProviderAvailability {
google_available: boolean;
exa_available: boolean;
tavily_available: boolean;
gemini_key_status: 'configured' | 'missing';
exa_key_status: 'configured' | 'missing';
tavily_key_status: 'configured' | 'missing';
}
export interface PersonaDefaults {
@@ -140,18 +142,85 @@ export const getResearchConfig = async (): Promise<ResearchConfigResponse> => {
/**
* Get or refresh research persona
* @param forceRefresh - If true, regenerate persona even if cache is valid
* @param forceRefresh - If true, regenerate persona even if cache is valid
*/
export const refreshResearchPersona = async (forceRefresh: boolean = false): Promise<ResearchPersona> => {
export const refreshResearchPersona = async (forceRefresh: boolean = false): Promise<ResearchPersona> => {
try {
const url = `/api/research/research-persona${forceRefresh ? '?force_refresh=true' : ''}`;
const url = `/api/research/research-persona${forceRefresh ? '?force_refresh=true' : ''}`;
const response = await apiClient.get(url);
return response.data;
} catch (error: any) {
console.error('[researchConfig] Error refreshing research persona:', error?.response?.status || error?.message);
// Preserve the original error so subscription errors can be detected
// The apiClient interceptor should handle 429 errors, but we preserve the error structure
console.error('[researchConfig] Error refreshing research persona:', error?.response?.status || error?.message);
// Preserve the original error so subscription errors can be detected
// The apiClient interceptor should handle 429 errors, but we preserve the error structure
throw error;
}
};
/**
* Competitor Analysis Response Interface
*/
export interface CompetitorAnalysisResponse {
success: boolean;
competitors?: Array<{
name?: string;
url?: string;
domain?: string;
description?: string;
similarity_score?: number;
[key: string]: any;
}>;
social_media_accounts?: Record<string, string>;
social_media_citations?: Array<{
platform?: string;
account?: string;
url?: string;
[key: string]: any;
}>;
research_summary?: {
total_competitors?: number;
industry_insights?: string;
[key: string]: any;
};
analysis_timestamp?: string;
error?: string;
}
/**
* Get competitor analysis data from onboarding
*/
export const getCompetitorAnalysis = async (): Promise<CompetitorAnalysisResponse> => {
console.log('[getCompetitorAnalysis] ===== START: Fetching competitor analysis =====');
try {
console.log('[getCompetitorAnalysis] Making GET request to /api/research/competitor-analysis');
const response = await apiClient.get('/api/research/competitor-analysis');
console.log('[getCompetitorAnalysis] ✅ Response received:', {
success: response.data?.success,
competitorsCount: response.data?.competitors?.length || 0,
error: response.data?.error,
fullResponse: response.data
});
return response.data;
} catch (error: any) {
const statusCode = error?.response?.status;
const errorMessage = error?.response?.data?.detail || error?.response?.data?.error || error?.message || 'Unknown error';
console.error('[getCompetitorAnalysis] ❌ ERROR:', {
status: statusCode,
message: errorMessage,
fullError: error,
responseData: error?.response?.data
});
// Return error response instead of throwing
const errorResponse = {
success: false,
error: errorMessage
};
console.log('[getCompetitorAnalysis] Returning error response:', errorResponse);
return errorResponse;
} finally {
console.log('[getCompetitorAnalysis] ===== END: Fetching competitor analysis =====');
}
};

View File

@@ -38,10 +38,14 @@ export interface SchedulerJob {
job_store: string;
user_job_store: string;
function_name?: string | null;
platform?: string; // For OAuth token monitoring tasks
task_id?: number; // For OAuth token monitoring tasks
platform?: string; // For OAuth token monitoring tasks and platform insights
task_id?: number; // For OAuth token monitoring tasks, website analysis, and platform insights
is_database_task?: boolean; // Flag to indicate DB task vs APScheduler job
frequency?: string; // For OAuth tasks (e.g., 'Weekly')
task_type?: string; // For website analysis tasks ('user_website' or 'competitor')
task_category?: string; // 'website_analysis', 'platform_insights', 'oauth_token_monitoring'
website_url?: string | null; // For website analysis tasks
competitor_id?: number | null; // For competitor website analysis tasks
}
export interface UserIsolation {
@@ -128,6 +132,11 @@ export interface SchedulerEventHistoryResponse {
limit: number;
offset: number;
has_more: boolean;
date_filter?: {
days: number;
cutoff_date: string;
showing_events_since: string;
};
}
/**
@@ -199,17 +208,19 @@ export const getSchedulerJobs = async (): Promise<SchedulerJobsResponse> => {
/**
* Get scheduler event history from database.
*
* @param limit - Number of events to return (1-1000, default: 100)
* @param limit - Number of events to return (1-500, default: 5 for initial load, expand to 50 on hover)
* @param offset - Pagination offset (default: 0)
* @param eventType - Filter by event type (check_cycle, interval_adjustment, start, stop, etc.)
* @param days - Number of days to look back (1-90, default: 7 days)
*/
export const getSchedulerEventHistory = async (
limit: number = 100,
limit: number = 5,
offset: number = 0,
eventType?: 'check_cycle' | 'interval_adjustment' | 'start' | 'stop' | 'job_scheduled' | 'job_cancelled' | 'job_completed' | 'job_failed'
eventType?: 'check_cycle' | 'interval_adjustment' | 'start' | 'stop' | 'job_scheduled' | 'job_cancelled' | 'job_completed' | 'job_failed',
days: number = 7
): Promise<SchedulerEventHistoryResponse> => {
try {
const params: any = { limit, offset };
const params: any = { limit, offset, days };
if (eventType) {
params.event_type = eventType;
}

View File

@@ -0,0 +1,122 @@
/**
* Website Analysis Monitoring API Client
* Provides typed functions for fetching website analysis monitoring data.
*/
import { apiClient } from './client';
// TypeScript interfaces
export interface WebsiteAnalysisTask {
id: number;
website_url: string;
task_type: 'user_website' | 'competitor';
competitor_id: string | null;
status: 'active' | 'failed' | 'paused';
last_check: string | null;
last_success: string | null;
last_failure: string | null;
failure_reason: string | null;
next_check: string | null;
frequency_days: number;
created_at: string;
updated_at: string;
}
export interface WebsiteAnalysisStatusResponse {
success: boolean;
data: {
user_id: string;
user_website_tasks: WebsiteAnalysisTask[];
competitor_tasks: WebsiteAnalysisTask[];
total_tasks: number;
active_tasks: number;
failed_tasks: number;
};
}
export interface WebsiteAnalysisExecutionLog {
id: number;
task_id: number;
website_url: string;
task_type: 'user_website' | 'competitor';
execution_date: string;
status: 'success' | 'failed' | 'running' | 'skipped';
result_data: any;
error_message: string | null;
execution_time_ms: number | null;
created_at: string;
}
export interface WebsiteAnalysisLogsResponse {
logs: WebsiteAnalysisExecutionLog[];
total_count: number;
limit: number;
offset: number;
has_more: boolean;
}
export interface RetryWebsiteAnalysisResponse {
success: boolean;
message: string;
task: {
id: number;
website_url: string;
status: string;
next_check: string | null;
};
}
/**
* Get website analysis status for a user
*/
export const getWebsiteAnalysisStatus = async (
userId: string
): Promise<WebsiteAnalysisStatusResponse> => {
try {
const response = await apiClient.get(`/api/scheduler/website-analysis/status/${userId}`);
return response.data;
} catch (error: any) {
console.error('Error fetching website analysis status:', error);
throw new Error(error.response?.data?.detail || 'Failed to fetch website analysis status');
}
};
/**
* Get execution logs for website analysis tasks
*/
export const getWebsiteAnalysisLogs = async (
userId: string,
limit: number = 10,
offset: number = 0,
taskId?: number
): Promise<WebsiteAnalysisLogsResponse> => {
try {
const params: any = { limit, offset };
if (taskId) {
params.task_id = taskId;
}
const response = await apiClient.get(`/api/scheduler/website-analysis/logs/${userId}`, {
params
});
return response.data;
} catch (error: any) {
console.error('Error fetching website analysis logs:', error);
throw new Error(error.response?.data?.detail || 'Failed to fetch website analysis logs');
}
};
/**
* Manually retry a failed website analysis task
*/
export const retryWebsiteAnalysis = async (
taskId: number
): Promise<RetryWebsiteAnalysisResponse> => {
try {
const response = await apiClient.post(`/api/scheduler/website-analysis/retry/${taskId}`);
return response.data;
} catch (error: any) {
console.error('Error retrying website analysis:', error);
throw new Error(error.response?.data?.detail || 'Failed to retry website analysis');
}
};