@@ -13,6 +13,7 @@ import { RequestyHandler } from "../requesty"
1313import { ApiHandlerOptions } from "../../../shared/api"
1414import { Package } from "../../../shared/package"
1515import { ApiHandlerCreateMessageMetadata } from "../../index"
16+ import { asyncStreamFrom , collectStream } from "../../../test-utils/stream"
1617
1718const mockCreate = vitest . fn ( )
1819
@@ -182,38 +183,31 @@ describe("RequestyHandler", () => {
182183 it ( "generates correct stream chunks" , async ( ) => {
183184 const handler = new RequestyHandler ( mockOptions )
184185
185- const mockStream = {
186- async * [ Symbol . asyncIterator ] ( ) {
187- yield {
188- id : mockOptions . requestyModelId ,
189- choices : [ { delta : { content : "test response" } } ] ,
190- }
191- yield {
192- id : "test-id" ,
193- choices : [ { delta : { } } ] ,
194- usage : {
195- prompt_tokens : 10 ,
196- completion_tokens : 20 ,
197- prompt_tokens_details : {
198- caching_tokens : 5 ,
199- cached_tokens : 2 ,
200- } ,
186+ const mockStream = asyncStreamFrom ( [
187+ {
188+ id : mockOptions . requestyModelId ,
189+ choices : [ { delta : { content : "test response" } } ] ,
190+ } ,
191+ {
192+ id : "test-id" ,
193+ choices : [ { delta : { } } ] ,
194+ usage : {
195+ prompt_tokens : 10 ,
196+ completion_tokens : 20 ,
197+ prompt_tokens_details : {
198+ caching_tokens : 5 ,
199+ cached_tokens : 2 ,
201200 } ,
202- }
201+ } ,
203202 } ,
204- }
203+ ] )
205204
206205 mockCreate . mockResolvedValue ( mockStream )
207206
208207 const systemPrompt = "test system prompt"
209208 const messages : Anthropic . Messages . MessageParam [ ] = [ { role : "user" as const , content : "test message" } ]
210209
211- const generator = handler . createMessage ( systemPrompt , messages )
212- const chunks = [ ]
213-
214- for await ( const chunk of generator ) {
215- chunks . push ( chunk )
216- }
210+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages ) )
217211
218212 // Verify stream chunks
219213 expect ( chunks ) . toHaveLength ( 2 ) // One text chunk and one usage chunk
@@ -257,15 +251,13 @@ describe("RequestyHandler", () => {
257251 modelMaxTokens : 32768 ,
258252 } )
259253
260- const mockStream = {
261- async * [ Symbol . asyncIterator ] ( ) {
262- yield {
263- id : "test-id" ,
264- choices : [ { delta : { } } ] ,
265- usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
266- }
254+ const mockStream = asyncStreamFrom ( [
255+ {
256+ id : "test-id" ,
257+ choices : [ { delta : { } } ] ,
258+ usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
267259 } ,
268- }
260+ ] )
269261
270262 mockCreate . mockResolvedValue ( mockStream )
271263
@@ -290,15 +282,13 @@ describe("RequestyHandler", () => {
290282 modelMaxTokens : 32768 ,
291283 } )
292284
293- const mockStream = {
294- async * [ Symbol . asyncIterator ] ( ) {
295- yield {
296- id : "test-id" ,
297- choices : [ { delta : { } } ] ,
298- usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
299- }
285+ const mockStream = asyncStreamFrom ( [
286+ {
287+ id : "test-id" ,
288+ choices : [ { delta : { } } ] ,
289+ usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
300290 } ,
301- }
291+ ] )
302292
303293 mockCreate . mockResolvedValue ( mockStream )
304294
@@ -323,15 +313,13 @@ describe("RequestyHandler", () => {
323313 modelMaxTokens : 32768 ,
324314 } )
325315
326- const mockStream = {
327- async * [ Symbol . asyncIterator ] ( ) {
328- yield {
329- id : "test-id" ,
330- choices : [ { delta : { } } ] ,
331- usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
332- }
316+ const mockStream = asyncStreamFrom ( [
317+ {
318+ id : "test-id" ,
319+ choices : [ { delta : { } } ] ,
320+ usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
333321 } ,
334- }
322+ ] )
335323
336324 mockCreate . mockResolvedValue ( mockStream )
337325
@@ -359,53 +347,47 @@ describe("RequestyHandler", () => {
359347
360348 it ( "streams reasoning chunks from delta.reasoning_content" , async ( ) => {
361349 const handler = new RequestyHandler ( mockOptions )
362- mockCreate . mockResolvedValue ( {
363- async * [ Symbol . asyncIterator ] ( ) {
364- yield { id : "1" , choices : [ { delta : { reasoning_content : "thinking..." } } ] }
365- yield { id : "1" , choices : [ { delta : { content : "answer" } } ] }
366- yield {
350+ mockCreate . mockResolvedValue (
351+ asyncStreamFrom ( [
352+ { id : "1" , choices : [ { delta : { reasoning_content : "thinking..." } } ] } ,
353+ { id : "1" , choices : [ { delta : { content : "answer" } } ] } ,
354+ {
367355 id : "1" ,
368356 choices : [ { delta : { } } ] ,
369357 usage : { prompt_tokens : 1 , completion_tokens : 1 } ,
370- }
371- } ,
372- } )
358+ } ,
359+ ] ) ,
360+ )
373361
374- const chunks : any [ ] = [ ]
375- for await ( const chunk of handler . createMessage ( "sys" , [ { role : "user" , content : "hi" } ] ) ) {
376- chunks . push ( chunk )
377- }
362+ const chunks = await collectStream ( handler . createMessage ( "sys" , [ { role : "user" , content : "hi" } ] ) )
378363
379364 expect ( chunks ) . toContainEqual ( { type : "reasoning" , text : "thinking..." } )
380365 } )
381366
382367 it ( "falls back to delta.reasoning when reasoning_content is absent" , async ( ) => {
383368 const handler = new RequestyHandler ( mockOptions )
384- mockCreate . mockResolvedValue ( {
385- async * [ Symbol . asyncIterator ] ( ) {
386- yield { id : "1" , choices : [ { delta : { reasoning : "router-style thought" } } ] }
387- yield {
369+ mockCreate . mockResolvedValue (
370+ asyncStreamFrom ( [
371+ { id : "1" , choices : [ { delta : { reasoning : "router-style thought" } } ] } ,
372+ {
388373 id : "1" ,
389374 choices : [ { delta : { } } ] ,
390375 usage : { prompt_tokens : 1 , completion_tokens : 1 } ,
391- }
392- } ,
393- } )
376+ } ,
377+ ] ) ,
378+ )
394379
395- const chunks : any [ ] = [ ]
396- for await ( const chunk of handler . createMessage ( "sys" , [ { role : "user" , content : "hi" } ] ) ) {
397- chunks . push ( chunk )
398- }
380+ const chunks = await collectStream ( handler . createMessage ( "sys" , [ { role : "user" , content : "hi" } ] ) )
399381
400382 expect ( chunks ) . toContainEqual ( { type : "reasoning" , text : "router-style thought" } )
401383 } )
402384
403385 it ( "prefers delta.reasoning_content over delta.reasoning when both are present" , async ( ) => {
404386 const handler = new RequestyHandler ( mockOptions )
405387
406- mockCreate . mockResolvedValue ( {
407- async * [ Symbol . asyncIterator ] ( ) {
408- yield {
388+ mockCreate . mockResolvedValue (
389+ asyncStreamFrom ( [
390+ {
409391 id : "1" ,
410392 choices : [
411393 {
@@ -415,20 +397,16 @@ describe("RequestyHandler", () => {
415397 } ,
416398 } ,
417399 ] ,
418- }
419- yield {
400+ } ,
401+ {
420402 id : "1" ,
421403 choices : [ { delta : { } } ] ,
422404 usage : { prompt_tokens : 1 , completion_tokens : 1 } ,
423- }
424- } ,
425- } )
426-
427- const chunks : any [ ] = [ ]
405+ } ,
406+ ] ) ,
407+ )
428408
429- for await ( const chunk of handler . createMessage ( "sys" , [ { role : "user" , content : "hi" } ] ) ) {
430- chunks . push ( chunk )
431- }
409+ const chunks = await collectStream ( handler . createMessage ( "sys" , [ { role : "user" , content : "hi" } ] ) )
432410
433411 const reasoningChunks = chunks . filter ( ( chunk ) => chunk . type === "reasoning" )
434412
@@ -459,15 +437,14 @@ describe("RequestyHandler", () => {
459437 ]
460438
461439 beforeEach ( ( ) => {
462- const mockStream = {
463- async * [ Symbol . asyncIterator ] ( ) {
464- yield {
440+ mockCreate . mockResolvedValue (
441+ asyncStreamFrom ( [
442+ {
465443 id : "test-id" ,
466444 choices : [ { delta : { content : "test response" } } ] ,
467- }
468- } ,
469- }
470- mockCreate . mockResolvedValue ( mockStream )
445+ } ,
446+ ] ) ,
447+ )
471448 } )
472449
473450 it ( "should include tools in request when tools are provided" , async ( ) => {
@@ -498,9 +475,9 @@ describe("RequestyHandler", () => {
498475 } )
499476
500477 it ( "should handle tool_call_partial chunks in streaming response" , async ( ) => {
501- const mockStreamWithToolCalls = {
502- async * [ Symbol . asyncIterator ] ( ) {
503- yield {
478+ mockCreate . mockResolvedValue (
479+ asyncStreamFrom ( [
480+ {
504481 id : "test-id" ,
505482 choices : [
506483 {
@@ -518,8 +495,8 @@ describe("RequestyHandler", () => {
518495 } ,
519496 } ,
520497 ] ,
521- }
522- yield {
498+ } ,
499+ {
523500 id : "test-id" ,
524501 choices : [
525502 {
@@ -535,26 +512,22 @@ describe("RequestyHandler", () => {
535512 } ,
536513 } ,
537514 ] ,
538- }
539- yield {
515+ } ,
516+ {
540517 id : "test-id" ,
541518 choices : [ { delta : { } } ] ,
542519 usage : { prompt_tokens : 10 , completion_tokens : 20 } ,
543- }
544- } ,
545- }
546- mockCreate . mockResolvedValue ( mockStreamWithToolCalls )
520+ } ,
521+ ] ) ,
522+ )
547523
548524 const metadata : ApiHandlerCreateMessageMetadata = {
549525 taskId : "test-task" ,
550526 tools : mockTools ,
551527 }
552528
553529 const handler = new RequestyHandler ( mockOptions )
554- const chunks = [ ]
555- for await ( const chunk of handler . createMessage ( systemPrompt , messages , metadata ) ) {
556- chunks . push ( chunk )
557- }
530+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages , metadata ) )
558531
559532 // Expect two tool_call_partial chunks and one usage chunk
560533 expect ( chunks ) . toHaveLength ( 3 )
0 commit comments