mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-22 00:30:19 +02:00
Coordinate initial conversation reveal, preserve message identity and reading anchors during live updates, and bound transcript reads with recoverable retries. Cover desktop/mobile navigation and rich task loading with actual-route browser tests. Verified all Linux CI gates, 5,575 local UI tests, eight layout browser scenarios, and recorded native Codex walkthroughs. Greptile: 5/5; all review findings resolved. Co-Authored-By: Paperclip <noreply@paperclip.ing>
36 lines
1.4 KiB
TypeScript
36 lines
1.4 KiB
TypeScript
export const TRANSCRIPT_REQUEST_TIMEOUT_MS = 15_000;
|
|
|
|
/** Bound history reads, including body consumption, and release coalesced GETs
|
|
* on timeout so Retry starts a fresh request. Late responses cannot commit. */
|
|
export function readTranscriptRequest<T>(request: (signal: AbortSignal) => Promise<T>, signal: AbortSignal): Promise<T> {
|
|
if (signal.aborted) return Promise.reject(new DOMException("History read cancelled", "AbortError"));
|
|
return new Promise<T>((resolve, reject) => {
|
|
const controller = new AbortController();
|
|
let settled = false;
|
|
const finish = (complete: () => void) => {
|
|
if (settled) return;
|
|
settled = true;
|
|
window.clearTimeout(timer);
|
|
signal.removeEventListener("abort", onAbort);
|
|
complete();
|
|
};
|
|
const onAbort = () => {
|
|
finish(() => reject(new DOMException("History read cancelled", "AbortError")));
|
|
controller.abort();
|
|
};
|
|
const timer = window.setTimeout(() => {
|
|
finish(() => reject(new Error("Run history took too long to load. Retry to load it.")));
|
|
controller.abort();
|
|
}, TRANSCRIPT_REQUEST_TIMEOUT_MS);
|
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
try {
|
|
request(controller.signal).then(
|
|
(value) => finish(() => resolve(value)),
|
|
(error) => finish(() => reject(error)),
|
|
);
|
|
} catch (error) {
|
|
finish(() => reject(error));
|
|
}
|
|
});
|
|
}
|