fix: export temporary chat response callbacks on Firefox

This commit is contained in:
Pionxzh
2026-08-28 01:44:10 +08:00
committed by Pionxzh
parent 87dbdf0c59
commit 66aeac8008
+37 -10
View File
@@ -21,7 +21,7 @@ export function checkIfTemporaryChatIsExportable() {
return !isTemporaryChat() || temporaryChatId !== null return !isTemporaryChat() || temporaryChatId !== null
} }
declare const exportFunction: (func: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>, context: any) => (input: RequestInfo | URL, init?: RequestInit) => Promise<Response> declare const exportFunction: <T extends (...args: never[]) => unknown>(func: T, context: object) => T
/** /**
* Temporary chats are hidden from the conversation list and their id never * Temporary chats are hidden from the conversation list and their id never
@@ -33,23 +33,50 @@ declare const exportFunction: (func: (input: RequestInfo | URL, init?: RequestIn
export function watchTemporaryChatId() { export function watchTemporaryChatId() {
const originalFetch = unsafeWindow.fetch const originalFetch = unsafeWindow.fetch
const logObserverError = (error: unknown) => {
console.error('[Exporter] Failed to observe the temporary chat response', error)
}
const observeResponse = (response: Response) => {
try {
if (!response.body) return
readConversationId(response.clone()).catch(logObserverError)
}
catch (error) {
logObserverError(error)
}
}
const ignoreFetchFailure = () => {}
const canExportToPage = typeof exportFunction === 'function'
const pageResponseObserver = canExportToPage
? exportFunction(observeResponse, unsafeWindow)
: observeResponse
const pageFetchFailureHandler = canExportToPage
? exportFunction(ignoreFetchFailure, unsafeWindow)
: ignoreFetchFailure
const patchedFetch = (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => { const patchedFetch = (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
// `fetch` needs its original receiver, or Chrome throws on invocation. // `fetch` needs its original receiver, or Chrome throws on invocation.
const response = originalFetch.call(unsafeWindow, input, init) const response = originalFetch.call(unsafeWindow, input, init)
if (isTemporaryChat()) { if (isTemporaryChat()) {
response.then((response) => { try {
if (!response.body) return response
const url = typeof input === 'string' const url = typeof input === 'string'
? input ? input
: input instanceof URL ? input.href : input.url : input instanceof URL ? input.href : input.url
if (!url.includes(CONVERSATION_STREAM_PATH)) return response if (url.includes(CONVERSATION_STREAM_PATH)) {
// Both callbacks must be callable from the page's Promise
// Read a copy so the page still receives the untouched stream. // realm. Handling rejection also prevents this observer
readConversationId(response.clone()) // branch from creating an unhandled rejection.
response.then(pageResponseObserver, pageFetchFailureHandler)
return response }
}) }
catch (error) {
// Observing a response must never affect ChatGPT's fetch call.
logObserverError(error)
}
} }
return response return response