🔃 fix: Token Refresh in Browser Only, Redirect on Refresh Failure (#9583)

* 🔃 fix: Token Refresh in Browser Only, Redirect on Refresh Failure

* chore: Update import for SearchResultData and fix FormattedToolResponse type build warning
This commit is contained in:
Danny Avila 2025-09-11 16:51:40 -04:00 committed by GitHub
parent 180046a3c5
commit e3a645e8fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 63 additions and 61 deletions

View file

@ -8,7 +8,7 @@ import {
StreamableHTTPOptionsSchema,
Tools,
} from 'librechat-data-provider';
import type { UIResource, TPlugin, TUser } from 'librechat-data-provider';
import type { SearchResultData, UIResource, TPlugin, TUser } from 'librechat-data-provider';
import type * as t from '@modelcontextprotocol/sdk/types.js';
import type { TokenMethods } from '@librechat/data-schemas';
import type { FlowStateManager } from '~/flow/manager';
@ -133,7 +133,7 @@ export type Artifacts =
sources: FileSearchSource[];
fileCitations?: boolean;
};
[Tools.web_search]?: import('librechat-data-provider').SearchResultData;
[Tools.web_search]?: SearchResultData;
files?: Array<{ id: string; name: string }>;
session_id?: string;
file_ids?: string[];
@ -144,10 +144,7 @@ export type FormattedContentResult = [string | FormattedContent[], undefined | A
export type ImageFormatter = (item: ImageContent) => FormattedContent;
export type FormattedToolResponse = [
string | FormattedContent[],
{ content: FormattedContent[] } | undefined,
];
export type FormattedToolResponse = FormattedContentResult;
export type ParsedServerConfig = MCPOptions & {
url?: string;

View file

@ -83,6 +83,7 @@ const processQueue = (error: AxiosError | null, token: string | null = null) =>
failedQueue = [];
};
if (typeof window !== 'undefined') {
axios.interceptors.response.use(
(response) => response,
async (error) => {
@ -97,6 +98,12 @@ axios.interceptors.response.use(
if (originalRequest.url?.includes('/api/auth/logout') === true) {
return Promise.reject(error);
}
if (originalRequest.url?.includes('/api/auth/refresh') === true) {
// Refresh token itself failed - redirect to login
console.log('Refresh token request failed, redirecting to login...');
window.location.href = '/login';
return Promise.reject(error);
}
if (error.response.status === 401 && !originalRequest._retry) {
console.warn('401 error, refreshing token');
@ -117,10 +124,7 @@ axios.interceptors.response.use(
isRefreshing = true;
try {
const response = await refreshToken(
// Handle edge case where we get a blank screen if the initial 401 error is from a refresh token request
originalRequest.url?.includes('api/auth/refresh') === true ? true : false,
);
const response = await refreshToken();
const token = response?.token ?? '';
@ -147,6 +151,7 @@ axios.interceptors.response.use(
return Promise.reject(error);
},
);
}
export default {
get: _get,