File tree Expand file tree Collapse file tree 2 files changed +53
-0
lines changed
Expand file tree Collapse file tree 2 files changed +53
-0
lines changed Original file line number Diff line number Diff line change @@ -188,6 +188,39 @@ describe('RelayClient', () => {
188188 // Should not throw
189189 expect ( ( ) => ( client as any ) . processFrame ( errorEnvelope ) ) . not . toThrow ( ) ;
190190 } ) ;
191+
192+ it ( 'rejects pending spawn when SpawnManager is disabled' , async ( ) => {
193+ const client = new RelayClient ( { reconnect : false , quiet : true } ) ;
194+ ( client as any ) . _state = 'READY' ;
195+ const sendMock = vi . fn ( ) . mockReturnValue ( true ) ;
196+ ( client as any ) . send = sendMock ;
197+
198+ const spawnPromise = client . spawn (
199+ {
200+ name : 'Worker' ,
201+ cli : 'codex' ,
202+ task : 'Do work' ,
203+ } ,
204+ 10000
205+ ) ;
206+
207+ const errorEnvelope : Envelope < ErrorPayload > = {
208+ v : 1 ,
209+ type : 'ERROR' ,
210+ id : 'err-spawn-disabled' ,
211+ ts : Date . now ( ) ,
212+ payload : {
213+ code : 'INTERNAL' as any ,
214+ message : 'SpawnManager not enabled. Configure spawnManager: true in daemon config.' ,
215+ fatal : false ,
216+ } ,
217+ } ;
218+
219+ ( client as any ) . processFrame ( errorEnvelope ) ;
220+
221+ await expect ( spawnPromise ) . rejects . toThrow ( 'SpawnManager not enabled' ) ;
222+ expect ( ( client as any ) . pendingSpawns . size ) . toBe ( 0 ) ;
223+ } ) ;
191224 } ) ;
192225
193226 describe ( 'sendMessage' , ( ) => {
Original file line number Diff line number Diff line change @@ -1849,6 +1849,21 @@ export class RelayClient {
18491849 console . error ( '[sdk] Server error:' , envelope . payload ) ;
18501850 }
18511851
1852+ const errorMessage = envelope . payload . message || 'Server error' ;
1853+ const isSpawnManagerDisabled =
1854+ envelope . payload . code === 'INTERNAL' &&
1855+ / s p a w n m a n a g e r n o t e n a b l e d / i. test ( errorMessage ) ;
1856+
1857+ // Fail fast for spawn-related operations when daemon cannot service them.
1858+ // Without this, spawn/release/input/list-workers calls sit until timeout.
1859+ if ( isSpawnManagerDisabled ) {
1860+ const err = new Error ( errorMessage ) ;
1861+ this . rejectPendingSpawns ( err ) ;
1862+ this . rejectPendingReleases ( err ) ;
1863+ this . rejectPendingSendInputs ( err ) ;
1864+ this . rejectPendingListWorkers ( err ) ;
1865+ }
1866+
18521867 if ( envelope . payload . code === 'RESUME_TOO_OLD' ) {
18531868 this . resumeToken = undefined ;
18541869 this . sessionId = undefined ;
@@ -1861,6 +1876,11 @@ export class RelayClient {
18611876 }
18621877 this . _destroyed = true ;
18631878 }
1879+
1880+ // Surface server-side ERROR frames to SDK consumers.
1881+ if ( this . onError ) {
1882+ this . onError ( new Error ( errorMessage ) ) ;
1883+ }
18641884 }
18651885
18661886 private handleDisconnect ( ) : void {
You can’t perform that action at this time.
0 commit comments