@@ -30,6 +30,25 @@ import { GenerateContentRequest } from '../types';
3030use ( sinonChai ) ;
3131use ( chaiAsPromised ) ;
3232
33+ /**
34+ * Converts the ReadableStream from response.body to an array of strings.
35+ */
36+ async function toStringArray (
37+ stream : ReadableStream < Uint8Array >
38+ ) : Promise < string [ ] > {
39+ const decoder = new TextDecoder ( ) ;
40+ const actual = [ ] ;
41+ const reader = stream . getReader ( ) ;
42+ while ( true ) {
43+ const { done, value } = await reader . read ( ) ;
44+ if ( done ) {
45+ break ;
46+ }
47+ actual . push ( decoder . decode ( value ) ) ;
48+ }
49+ return actual ;
50+ }
51+
3352describe ( 'ChromeAdapter' , ( ) => {
3453 describe ( 'isAvailable' , ( ) => {
3554 it ( 'returns false if mode is only cloud' , async ( ) => {
@@ -307,4 +326,52 @@ describe('ChromeAdapter', () => {
307326 } ) ;
308327 } ) ;
309328 } ) ;
329+ describe ( 'generateContentStreamOnDevice' , ( ) => {
330+ it ( 'generates content stream' , async ( ) => {
331+ const languageModelProvider = {
332+ create : ( ) => Promise . resolve ( { } )
333+ } as LanguageModel ;
334+ const languageModel = {
335+ promptStreaming : _i => new ReadableStream ( )
336+ } as LanguageModel ;
337+ const createStub = stub ( languageModelProvider , 'create' ) . resolves (
338+ languageModel
339+ ) ;
340+ const part = 'hi' ;
341+ const promptStub = stub ( languageModel , 'promptStreaming' ) . returns (
342+ new ReadableStream ( {
343+ start ( controller ) {
344+ controller . enqueue ( [ part ] ) ;
345+ controller . close ( ) ;
346+ }
347+ } )
348+ ) ;
349+ const onDeviceParams = { } as LanguageModelCreateOptions ;
350+ const adapter = new ChromeAdapter (
351+ languageModelProvider ,
352+ 'prefer_on_device' ,
353+ onDeviceParams
354+ ) ;
355+ const request = {
356+ contents : [ { role : 'user' , parts : [ { text : 'anything' } ] } ]
357+ } as GenerateContentRequest ;
358+ const response = await adapter . generateContentStreamOnDevice ( request ) ;
359+ expect ( createStub ) . to . have . been . calledOnceWith ( onDeviceParams ) ;
360+ expect ( promptStub ) . to . have . been . calledOnceWith ( [
361+ {
362+ role : request . contents [ 0 ] . role ,
363+ content : [
364+ {
365+ type : 'text' ,
366+ content : request . contents [ 0 ] . parts [ 0 ] . text
367+ }
368+ ]
369+ }
370+ ] ) ;
371+ const actual = await toStringArray ( response . body ! ) ;
372+ expect ( actual ) . to . deep . equal ( [
373+ `data: {"candidates":[{"content":{"role":"model","parts":[{"text":["${ part } "]}]}}]}\n\n`
374+ ] ) ;
375+ } ) ;
376+ } ) ;
310377} ) ;
0 commit comments