mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
🐛 fix: the klavis in onboarding connect timeout fixed (#11918)
fix: the klavis in onboarding connect timeout fixed
This commit is contained in:
@@ -104,7 +104,7 @@ const KlavisToolAuthItem = memo<KlavisToolAuthItemProps>(({ tool, onAuthComplete
|
||||
try {
|
||||
await refreshKlavisServerTools(identifier);
|
||||
} catch (error) {
|
||||
console.error('[Klavis] Failed to check auth status:', error);
|
||||
console.debug('[Klavis] Polling check (expected during auth):', error);
|
||||
}
|
||||
}, POLL_INTERVAL_MS);
|
||||
|
||||
@@ -129,7 +129,8 @@ const KlavisToolAuthItem = memo<KlavisToolAuthItemProps>(({ tool, onAuthComplete
|
||||
windowCheckIntervalRef.current = null;
|
||||
}
|
||||
oauthWindowRef.current = null;
|
||||
refreshKlavisServerTools(identifier);
|
||||
// Start polling after window closes
|
||||
startFallbackPolling(identifier);
|
||||
}
|
||||
} catch {
|
||||
if (windowCheckIntervalRef.current) {
|
||||
|
||||
@@ -120,7 +120,7 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
|
||||
try {
|
||||
await refreshKlavisServerTools(serverName);
|
||||
} catch (error) {
|
||||
console.error('[Klavis] Failed to check auth status:', error);
|
||||
console.debug('[Klavis] Polling check (expected during auth):', error);
|
||||
}
|
||||
}, POLL_INTERVAL_MS);
|
||||
|
||||
@@ -145,8 +145,8 @@ const KlavisSkillItem = memo<KlavisSkillItemProps>(({ serverType, server }) => {
|
||||
windowCheckIntervalRef.current = null;
|
||||
}
|
||||
oauthWindowRef.current = null;
|
||||
await refreshKlavisServerTools(serverName);
|
||||
setIsWaitingAuth(false);
|
||||
// Start polling after window closes
|
||||
startFallbackPolling(serverName);
|
||||
}
|
||||
} catch {
|
||||
console.log('[Klavis] COOP blocked window.closed access, falling back to polling');
|
||||
|
||||
@@ -5,6 +5,7 @@ import { KlavisServerStatus } from '@/store/tool/slices/klavisStore';
|
||||
|
||||
const POLL_INTERVAL_MS = 1000;
|
||||
const POLL_TIMEOUT_MS = 15_000;
|
||||
const WINDOW_CLOSED_POLL_TIMEOUT_MS = 4000; // Shorter timeout when window is closed
|
||||
|
||||
interface UseKlavisOAuthProps {
|
||||
serverStatus?: KlavisServerStatus;
|
||||
@@ -50,14 +51,14 @@ export const useKlavisOAuth = ({ serverStatus }: UseKlavisOAuthProps) => {
|
||||
}, [serverStatus, isWaitingAuth, cleanup]);
|
||||
|
||||
const startFallbackPolling = useCallback(
|
||||
(serverName: string) => {
|
||||
(serverName: string, timeoutMs: number = POLL_TIMEOUT_MS) => {
|
||||
if (pollIntervalRef.current) return;
|
||||
|
||||
pollIntervalRef.current = setInterval(async () => {
|
||||
try {
|
||||
await refreshKlavisServerTools(serverName);
|
||||
} catch (error) {
|
||||
console.error('[Klavis] Failed to check auth status:', error);
|
||||
console.debug('[Klavis] Polling check (expected during auth):', error);
|
||||
}
|
||||
}, POLL_INTERVAL_MS);
|
||||
|
||||
@@ -67,7 +68,7 @@ export const useKlavisOAuth = ({ serverStatus }: UseKlavisOAuthProps) => {
|
||||
pollIntervalRef.current = null;
|
||||
}
|
||||
setIsWaitingAuth(false);
|
||||
}, POLL_TIMEOUT_MS);
|
||||
}, timeoutMs);
|
||||
},
|
||||
[refreshKlavisServerTools],
|
||||
);
|
||||
@@ -77,23 +78,29 @@ export const useKlavisOAuth = ({ serverStatus }: UseKlavisOAuthProps) => {
|
||||
windowCheckIntervalRef.current = setInterval(() => {
|
||||
try {
|
||||
if (oauthWindow.closed) {
|
||||
// Stop monitoring window
|
||||
if (windowCheckIntervalRef.current) {
|
||||
clearInterval(windowCheckIntervalRef.current);
|
||||
windowCheckIntervalRef.current = null;
|
||||
}
|
||||
oauthWindowRef.current = null;
|
||||
refreshKlavisServerTools(serverName);
|
||||
|
||||
// Start polling to check auth status after window closes
|
||||
// Use shorter timeout since user has closed the window
|
||||
// Keep loading state until we confirm success or timeout
|
||||
startFallbackPolling(serverName, WINDOW_CLOSED_POLL_TIMEOUT_MS);
|
||||
}
|
||||
} catch {
|
||||
if (windowCheckIntervalRef.current) {
|
||||
clearInterval(windowCheckIntervalRef.current);
|
||||
windowCheckIntervalRef.current = null;
|
||||
}
|
||||
// Use default timeout for fallback polling
|
||||
startFallbackPolling(serverName);
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
[refreshKlavisServerTools, startFallbackPolling],
|
||||
[startFallbackPolling],
|
||||
);
|
||||
|
||||
const openOAuthWindow = useCallback(
|
||||
|
||||
@@ -88,7 +88,7 @@ const KlavisServerItem = memo<KlavisServerItemProps>(
|
||||
try {
|
||||
await refreshKlavisServerTools(serverName);
|
||||
} catch (error) {
|
||||
console.error('[Klavis] Failed to check auth status:', error);
|
||||
console.debug('[Klavis] Polling check (expected during auth):', error);
|
||||
}
|
||||
}, POLL_INTERVAL_MS);
|
||||
|
||||
@@ -121,8 +121,8 @@ const KlavisServerItem = memo<KlavisServerItemProps>(
|
||||
}
|
||||
oauthWindowRef.current = null;
|
||||
|
||||
// 窗口关闭后立即检查一次认证状态
|
||||
refreshKlavisServerTools(serverName);
|
||||
// 窗口关闭后开始轮询检查认证状态
|
||||
startFallbackPolling(serverName);
|
||||
}
|
||||
} catch {
|
||||
// COOP 阻止了访问,降级到轮询方案
|
||||
|
||||
@@ -124,6 +124,7 @@ export const klavisRouter = router({
|
||||
|
||||
/**
|
||||
* Get server instance status from Klavis API
|
||||
* Returns error object instead of throwing on auth errors (useful for polling)
|
||||
*/
|
||||
getServerInstance: klavisProcedure
|
||||
.input(
|
||||
@@ -132,16 +133,43 @@ export const klavisRouter = router({
|
||||
}),
|
||||
)
|
||||
.query(async ({ input, ctx }) => {
|
||||
const response = await ctx.klavisClient.mcpServer.getServerInstance(input.instanceId);
|
||||
return {
|
||||
authNeeded: response.authNeeded,
|
||||
externalUserId: response.externalUserId,
|
||||
instanceId: response.instanceId,
|
||||
isAuthenticated: response.isAuthenticated,
|
||||
oauthUrl: response.oauthUrl,
|
||||
platform: response.platform,
|
||||
serverName: response.serverName,
|
||||
};
|
||||
try {
|
||||
const response = await ctx.klavisClient.mcpServer.getServerInstance(input.instanceId);
|
||||
return {
|
||||
authNeeded: response.authNeeded,
|
||||
error: undefined,
|
||||
externalUserId: response.externalUserId,
|
||||
instanceId: response.instanceId,
|
||||
isAuthenticated: response.isAuthenticated,
|
||||
oauthUrl: response.oauthUrl,
|
||||
platform: response.platform,
|
||||
serverName: response.serverName,
|
||||
};
|
||||
} catch (error) {
|
||||
// Check if this is an authentication error
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
const isAuthError =
|
||||
errorMessage.includes('Invalid API key or instance ID') ||
|
||||
errorMessage.includes('Status code: 401');
|
||||
|
||||
// For auth errors, return error object instead of throwing
|
||||
// This prevents 500 errors in logs during polling
|
||||
if (isAuthError) {
|
||||
return {
|
||||
authNeeded: true,
|
||||
error: 'AUTH_ERROR',
|
||||
externalUserId: undefined,
|
||||
instanceId: input.instanceId,
|
||||
isAuthenticated: false,
|
||||
oauthUrl: undefined,
|
||||
platform: undefined,
|
||||
serverName: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
// For other errors, still throw
|
||||
throw error;
|
||||
}
|
||||
}),
|
||||
|
||||
getUserIntergrations: klavisProcedure
|
||||
|
||||
@@ -210,10 +210,30 @@ export const createKlavisStoreSlice: StateCreator<
|
||||
instanceId: server.instanceId,
|
||||
});
|
||||
|
||||
// If server returned an auth error (during polling), silently return
|
||||
// This happens when user is still in the process of authorizing
|
||||
if (instanceStatus.error === 'AUTH_ERROR') {
|
||||
set(
|
||||
produce((draft: KlavisStoreState) => {
|
||||
draft.loadingServerIds.delete(identifier);
|
||||
}),
|
||||
false,
|
||||
n('refreshKlavisServerTools/pendingAuth'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// If authentication failed, remove server and reset status
|
||||
if (!instanceStatus.isAuthenticated) {
|
||||
if (!instanceStatus.authNeeded) {
|
||||
// If no authentication needed, all is well
|
||||
set(
|
||||
produce((draft: KlavisStoreState) => {
|
||||
draft.loadingServerIds.delete(identifier);
|
||||
}),
|
||||
false,
|
||||
n('refreshKlavisServerTools/noAuthNeeded'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user