Save local changes (GSC/Bing integrations) before merging PR #354
This commit is contained in:
@@ -545,7 +545,7 @@ class TaskWorkflowOrchestrator {
|
||||
private loadPersistedWorkflows(): void {
|
||||
if (this.config.persistProgress) {
|
||||
try {
|
||||
const keys = Object.keys(localStorage).filter(key => key.startsWith('workflow-'));
|
||||
const keys = Object.keys(localStorage).filter(key => key.startsWith('workflow-') && key !== 'workflow-store');
|
||||
keys.forEach(key => {
|
||||
const workflowData = localStorage.getItem(key);
|
||||
if (workflowData) {
|
||||
@@ -554,7 +554,8 @@ class TaskWorkflowOrchestrator {
|
||||
|
||||
// Ensure workflow has required properties
|
||||
if (!workflow.id || !workflow.date || !workflow.userId) {
|
||||
console.warn(`Invalid workflow data for key ${key}, skipping`);
|
||||
console.warn(`Invalid workflow data for key ${key}, skipping and cleaning up`);
|
||||
localStorage.removeItem(key);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ const BILLING_BASE_URL = API_BASE_URL
|
||||
// Create axios instance with default config
|
||||
const billingAPI = axios.create({
|
||||
baseURL: BILLING_BASE_URL,
|
||||
timeout: 10000,
|
||||
timeout: 60000, // Increased to 60s to prevent timeouts in dev/slow networks
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
@@ -202,6 +202,7 @@ function coerceUsageStats(raw: any): UsageStats {
|
||||
const geminiData = providerBreakdown.gemini;
|
||||
const mistralData = providerBreakdown.mistral; // Backend sends 'mistral' for HuggingFace
|
||||
const huggingfaceData = providerBreakdown.huggingface;
|
||||
const wavespeedData = providerBreakdown.wavespeed;
|
||||
|
||||
// Create properly typed ProviderUsage objects
|
||||
const geminiUsage: ProviderUsage = geminiData && typeof geminiData === 'object' && 'calls' in geminiData
|
||||
@@ -214,11 +215,16 @@ function coerceUsageStats(raw: any): UsageStats {
|
||||
: (mistralData && typeof mistralData === 'object' && 'calls' in mistralData)
|
||||
? { calls: Number(mistralData.calls) || 0, tokens: Number(mistralData.tokens) || 0, cost: Number(mistralData.cost) || 0 }
|
||||
: { calls: 0, tokens: 0, cost: 0 };
|
||||
|
||||
const wavespeedUsage: ProviderUsage = wavespeedData && typeof wavespeedData === 'object' && 'calls' in wavespeedData
|
||||
? { calls: Number(wavespeedData.calls) || 0, tokens: Number(wavespeedData.tokens) || 0, cost: Number(wavespeedData.cost) || 0 }
|
||||
: { calls: 0, tokens: 0, cost: 0 };
|
||||
|
||||
// Create ProviderBreakdown with only gemini and huggingface
|
||||
const providerBreakdownCoerced: ProviderBreakdown = {
|
||||
gemini: geminiUsage,
|
||||
huggingface: huggingfaceUsage,
|
||||
wavespeed: wavespeedUsage,
|
||||
};
|
||||
|
||||
// Extract usage percentages - only include gemini and huggingface
|
||||
@@ -234,7 +240,7 @@ function coerceUsageStats(raw: any): UsageStats {
|
||||
// Calculate total_cost from provider breakdown
|
||||
// Always calculate from provider breakdown to ensure accuracy, but prefer backend total if it's more accurate
|
||||
const backendTotalCost = typeof raw?.total_cost === 'number' ? raw.total_cost : 0;
|
||||
const calculatedTotalCost = geminiUsage.cost + huggingfaceUsage.cost;
|
||||
const calculatedTotalCost = geminiUsage.cost + huggingfaceUsage.cost + wavespeedUsage.cost;
|
||||
|
||||
// Use the maximum of backend cost and calculated cost to ensure we show the actual cost
|
||||
// If backend cost is 0 but we have provider costs, use calculated cost
|
||||
@@ -249,18 +255,20 @@ function coerceUsageStats(raw: any): UsageStats {
|
||||
finalTotalCost: totalCost,
|
||||
geminiCost: geminiUsage.cost,
|
||||
huggingfaceCost: huggingfaceUsage.cost,
|
||||
wavespeedCost: wavespeedUsage.cost,
|
||||
geminiCalls: geminiUsage.calls,
|
||||
huggingfaceCalls: huggingfaceUsage.calls,
|
||||
wavespeedCalls: wavespeedUsage.calls,
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate total_calls and total_tokens from provider breakdown if needed
|
||||
const backendTotalCalls = typeof raw?.total_calls === 'number' ? raw.total_calls : 0;
|
||||
const calculatedTotalCalls = geminiUsage.calls + huggingfaceUsage.calls;
|
||||
const calculatedTotalCalls = geminiUsage.calls + huggingfaceUsage.calls + wavespeedUsage.calls;
|
||||
const totalCalls = backendTotalCalls > 0 ? backendTotalCalls : calculatedTotalCalls;
|
||||
|
||||
const backendTotalTokens = typeof raw?.total_tokens === 'number' ? raw.total_tokens : 0;
|
||||
const calculatedTotalTokens = geminiUsage.tokens + huggingfaceUsage.tokens;
|
||||
const calculatedTotalTokens = geminiUsage.tokens + huggingfaceUsage.tokens + wavespeedUsage.tokens;
|
||||
const totalTokens = backendTotalTokens > 0 ? backendTotalTokens : calculatedTotalTokens;
|
||||
|
||||
const coerced: UsageStats = {
|
||||
|
||||
@@ -233,7 +233,7 @@ export interface BlogPublishResponse {
|
||||
post_id?: string;
|
||||
}
|
||||
|
||||
export interface TaskStatusResponse {
|
||||
export interface TaskStatusResponse<T = BlogResearchResponse> {
|
||||
task_id: string;
|
||||
status: 'pending' | 'running' | 'completed' | 'failed';
|
||||
created_at: string;
|
||||
@@ -241,7 +241,7 @@ export interface TaskStatusResponse {
|
||||
timestamp: string;
|
||||
message: string;
|
||||
}>;
|
||||
result?: BlogResearchResponse;
|
||||
result?: T;
|
||||
error?: string;
|
||||
// Subscription error details (set by backend when subscription limit is exceeded)
|
||||
error_status?: number; // HTTP status code (429 for usage limit, 402 for subscription expired)
|
||||
|
||||
@@ -26,7 +26,7 @@ const MONITORING_BASE_URL = API_BASE_URL
|
||||
// Use shorter timeout for health checks to prevent blocking dashboard
|
||||
const monitoringAPI = axios.create({
|
||||
baseURL: MONITORING_BASE_URL,
|
||||
timeout: 5000, // Reduced from 10000 to 5000ms for faster failure
|
||||
timeout: 30000, // Increased from 5000 to 30000ms to prevent false positives in dev
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user