Skip to content

Commit

Permalink
Merge pull request #34 from memori-ai/fix_completion_provider_status
Browse files Browse the repository at this point in the history
Fix completion provider status
  • Loading branch information
nzambello authored Dec 16, 2024
2 parents 764f976 + 9a04d6d commit 2d2abe6
Show file tree
Hide file tree
Showing 8 changed files with 440 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@

.memori--completion-provider-status--tooltip.memori-tooltip .memori-tooltip--content p+p {
margin-top: 1em;
}

.memori--completion-provider-status--loading {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import './CompletionProviderStatus.css';

const meta: Meta = {
title: 'Completion Provider Status',
component: CompletionProviderStatus,
component: CompletionProviderStatus as React.ComponentType<any>,
argTypes: {},
parameters: {
layout: 'centered',
Expand Down
161 changes: 95 additions & 66 deletions src/components/CompletionProviderStatus/CompletionProviderStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useCallback } from 'react';
import Tooltip from '../ui/Tooltip';
import Warning from '../icons/Warning';
import { useTranslation } from 'react-i18next';
import Spin from '../ui/Spin';

type Status =
| 'operational'
Expand All @@ -15,60 +16,46 @@ export interface Props {
provider?: string;
}

const initProviderStatus = (
provider?: Props['provider'] | 'DEFAULT'
): {
getStatus: () => Promise<Status>;
interface ProviderConfig {
statusUrl: string;
statusPage: string;
} => {
switch (provider) {
case 'OpenAI':
return {
getStatus: async () => {
const res = await fetch(
'https://status.openai.com/api/v2/summary.json'
);
const data = await res.json();
const status = data.components.find(
(component: { name: string }) => component.name === 'API'
)?.status as Status;
return status ?? 'operational';
},
statusPage: 'https://status.openai.com/',
};
case 'Mistral':
return {
getStatus: async () => {
const res = await fetch(
'https://status.mistral-data.com/api/v2/summary.json'
);
const data = await res.json();
const status = data.components.find(
(component: { name: string }) => component.name === 'API'
)?.status as Status;
return status ?? 'operational';
},
statusPage: 'https://status.mistral-data.com/',
};
case 'Anthropic':
return {
getStatus: async () => {
const res = await fetch(
'https://status.anthropic.com/api/v2/summary.json'
);
const data = await res.json();
const status = data.components.find(
(component: { name: string }) => component.name === 'API'
)?.status as Status;
return status ?? 'operational';
},
statusPage: 'https://status.anthropic.com/',
};
default:
return {
getStatus: async () => 'operational',
statusPage: '',
};
}

const PROVIDER_CONFIGS: Record<string, ProviderConfig> = {
OpenAI: {
statusUrl: 'https://status.openai.com/api/v2/summary.json',
statusPage: 'https://status.openai.com/',
},
Mistral: {
statusUrl: 'https://status.mistral-data.com/api/v2/summary.json',
statusPage: 'https://status.mistral-data.com/',
},
Anthropic: {
statusUrl: 'https://status.anthropic.com/api/v2/summary.json',
statusPage: 'https://status.anthropic.com/',
},
};

// Modified to handle fetch errors and use cross-fetch
const fetchProviderStatus = async (statusUrl: string): Promise<Status> => {
try {
// Use cross-fetch instead of native fetch
const response = await fetch(statusUrl);

if (!response.ok) {
console.warn(`Status API returned ${response.status}`);
return 'operational'; // Fallback to operational on API errors
}

const data = await response.json();
const apiComponent = data.components?.find(
(component: { name: string }) => component.name === 'API'
);

return apiComponent?.status as Status ?? 'operational';
} catch (error) {
console.error('Error fetching provider status:', error);
return 'operational'; // Fallback to operational on network errors
}
};

Expand All @@ -78,19 +65,61 @@ const CompletionProviderStatus = ({
}: Props) => {
const { t } = useTranslation();
const [status, setStatus] = useState<Status>(forceStatus ?? 'operational');
const [isLoading, setIsLoading] = useState(false);

const config = PROVIDER_CONFIGS[provider];

const providerStatus = initProviderStatus(provider);
const getStatus = useCallback(async () => {
if (!config) return 'operational';
return fetchProviderStatus(config.statusUrl);
}, [config]);

useEffect(() => {
if (forceStatus) return;
let mounted = true;
const abortController = new AbortController();

providerStatus
.getStatus()
.then(status => setStatus(status))
.catch(console.log);
}, [forceStatus, providerStatus]);
const checkStatus = async () => {
if (forceStatus) return;

setIsLoading(true);
try {
const newStatus = await getStatus();
if (mounted) {
setStatus(newStatus);
}
} catch (error) {
console.error('Failed to check status:', error);
if (mounted) {
setStatus('operational'); // Fallback on error
}
} finally {
if (mounted) {
setIsLoading(false);
}
}
};

checkStatus();

return () => {
mounted = false;
abortController.abort();
};
}, [forceStatus, getStatus]);

if (isLoading) {
return (
<div className="memori--completion-provider-status--loading">
<Spin spinning={true} />
</div>
);
}

if (!status || status === 'operational') {
return null;
}

return status !== 'operational' ? (
return (
<Tooltip
className="memori--completion-provider-status--tooltip"
align="topLeft"
Expand All @@ -101,10 +130,10 @@ const CompletionProviderStatus = ({
provider: provider ?? t('completionProviderFallbackName'),
})}
</p>
{!!providerStatus.statusPage?.length && (
{config?.statusPage && (
<p>
<a
href={providerStatus.statusPage}
href={config.statusPage}
rel="noopener noreferrer"
target="_blank"
>
Expand All @@ -117,7 +146,7 @@ const CompletionProviderStatus = ({
>
<Warning className="memori--completion-provider-status--icon" />
</Tooltip>
) : null;
);
};

export default CompletionProviderStatus;
export default CompletionProviderStatus;
Loading

0 comments on commit 2d2abe6

Please sign in to comment.