@@ -89,23 +89,61 @@ const log = createLogger("plugin");
8989if ( typeof ( AbortSignal as any ) . any !== "function" ) {
9090 ( AbortSignal as any ) . any = function ( signals : AbortSignal [ ] ) : AbortSignal {
9191 const controller = new AbortController ( ) ;
92+ const onAbort = ( ) => {
93+ const firstAborted = signals . find ( s => s . aborted ) ;
94+ controller . abort ( firstAborted ?. reason ) ;
95+ cleanup ( ) ;
96+ } ;
97+ const cleanup = ( ) => {
98+ for ( const signal of signals ) {
99+ signal . removeEventListener ( "abort" , onAbort ) ;
100+ }
101+ } ;
92102 for ( const signal of signals ) {
93103 if ( signal . aborted ) {
94104 controller . abort ( signal . reason ) ;
95105 return controller . signal ;
96106 }
97- signal . addEventListener (
98- "abort" ,
99- ( ) => {
100- controller . abort ( signal . reason ) ;
101- } ,
102- { once : true }
103- ) ;
107+ signal . addEventListener ( "abort" , onAbort , { once : true } ) ;
104108 }
109+ controller . signal . addEventListener ( "abort" , cleanup , { once : true } ) ;
105110 return controller . signal ;
106111 } ;
107112}
108113
114+ /**
115+ * Simple combinator for multiple AbortSignals for environments where AbortSignal.any is missing.
116+ */
117+ function mergeAbortSignals ( ...signals : ( AbortSignal | undefined ) [ ] ) : AbortSignal {
118+ const activeSignals = signals . filter ( ( s ) : s is AbortSignal => s !== undefined ) ;
119+ if ( activeSignals . length === 0 ) return new AbortController ( ) . signal ;
120+ if ( activeSignals . length === 1 ) return activeSignals [ 0 ] as AbortSignal ;
121+
122+ if ( typeof ( AbortSignal as any ) . any === 'function' ) {
123+ return ( AbortSignal as any ) . any ( activeSignals ) ;
124+ }
125+
126+ const controller = new AbortController ( ) ;
127+ const onAbort = ( ) => {
128+ const firstAborted = activeSignals . find ( s => s . aborted ) ;
129+ controller . abort ( firstAborted ?. reason ) ;
130+ cleanup ( ) ;
131+ } ;
132+ const cleanup = ( ) => {
133+ for ( const signal of activeSignals ) {
134+ signal . removeEventListener ( "abort" , onAbort ) ;
135+ }
136+ } ;
137+ for ( const signal of activeSignals ) {
138+ if ( signal . aborted ) {
139+ controller . abort ( signal . reason ) ;
140+ return controller . signal ;
141+ }
142+ signal . addEventListener ( "abort" , onAbort , { once : true } ) ;
143+ }
144+ return controller . signal ;
145+ }
146+
109147// Module-level toast debounce to persist across requests (fixes toast spam)
110148const rateLimitToastCooldowns = new Map < string , number > ( ) ;
111149const RATE_LIMIT_TOAST_COOLDOWN_MS = 5000 ;
@@ -2063,10 +2101,17 @@ export const createAntigravityPlugin = (providerId: string) => async (
20632101 ? Math . min ( timeoutMs * 3 , 1800000 )
20642102 : timeoutMs ;
20652103
2066- const timeoutSignal = AbortSignal . timeout ( effectiveTimeoutMs ) ;
2067- const combinedSignal = abortSignal
2068- ? ( AbortSignal as any ) . any ( [ abortSignal , timeoutSignal ] )
2069- : timeoutSignal ;
2104+ // Safely create timeout signal with fallback for older Node.js versions
2105+ let timeoutSignal : AbortSignal ;
2106+ if ( typeof AbortSignal . timeout === 'function' ) {
2107+ timeoutSignal = AbortSignal . timeout ( effectiveTimeoutMs ) ;
2108+ } else {
2109+ const controller = new AbortController ( ) ;
2110+ timeoutSignal = controller . signal ;
2111+ }
2112+
2113+ // Safely create combined signal with polyfill/fallback
2114+ const combinedSignal = mergeAbortSignals ( abortSignal , timeoutSignal ) ;
20702115
20712116 const response = await fetch ( prepared . request , {
20722117 ...prepared . init ,
0 commit comments