fix(ai): timeout Codex SSE header stalls
This commit is contained in:
41
packages/ai/src/utils/abort-signals.ts
Normal file
41
packages/ai/src/utils/abort-signals.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export interface CombinedAbortSignal {
|
||||
signal?: AbortSignal;
|
||||
cleanup: () => void;
|
||||
}
|
||||
|
||||
export function combineAbortSignals(signals: readonly (AbortSignal | undefined)[]): CombinedAbortSignal {
|
||||
const activeSignals = signals.filter((signal): signal is AbortSignal => signal !== undefined);
|
||||
if (activeSignals.length === 0) {
|
||||
return { cleanup: () => {} };
|
||||
}
|
||||
if (activeSignals.length === 1) {
|
||||
return { signal: activeSignals[0], cleanup: () => {} };
|
||||
}
|
||||
|
||||
const controller = new AbortController();
|
||||
const listeners: Array<{ signal: AbortSignal; listener: () => void }> = [];
|
||||
const abort = (signal: AbortSignal) => {
|
||||
if (!controller.signal.aborted) {
|
||||
controller.abort(signal.reason);
|
||||
}
|
||||
};
|
||||
|
||||
for (const signal of activeSignals) {
|
||||
if (signal.aborted) {
|
||||
abort(signal);
|
||||
break;
|
||||
}
|
||||
const listener = () => abort(signal);
|
||||
signal.addEventListener("abort", listener, { once: true });
|
||||
listeners.push({ signal, listener });
|
||||
}
|
||||
|
||||
return {
|
||||
signal: controller.signal,
|
||||
cleanup: () => {
|
||||
for (const { signal, listener } of listeners) {
|
||||
signal.removeEventListener("abort", listener);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user