@@ -118,6 +118,69 @@ describeSmoke('Ollama live smoke', () => {
118118 } ) ;
119119} ) ;
120120
121+ describeSmoke ( 'generateWithUsage token metering' , ( ) => {
122+ jest . setTimeout ( 60_000 ) ;
123+
124+ it ( 'returns content and non-zero usage in batch mode' , async ( ) => {
125+ const client = new OllamaClient ( baseUrl ) ;
126+ const result = await client . generateWithUsage ( {
127+ model : modelId ,
128+ prompt : 'Reply with exactly the single word PING and nothing else.' ,
129+ maxTokens : 128 ,
130+ temperature : 0 ,
131+ } ) ;
132+
133+ expect ( result . content . toLowerCase ( ) ) . toContain ( 'ping' ) ;
134+ expect ( result . model ) . toBeTruthy ( ) ;
135+ expect ( result . usage . input ) . toBeGreaterThan ( 0 ) ;
136+ expect ( result . usage . output ) . toBeGreaterThan ( 0 ) ;
137+ expect ( result . usage . totalTokens ) . toBeGreaterThanOrEqual (
138+ result . usage . input + result . usage . output ,
139+ ) ;
140+ expect ( result . stopReason ) . toBe ( 'stop' ) ;
141+ } ) ;
142+
143+ it ( 'streams chunks and returns usage after completion' , async ( ) => {
144+ const client = new OllamaClient ( baseUrl ) ;
145+ const chunks : string [ ] = [ ] ;
146+ const result = await client . generateWithUsage (
147+ {
148+ model : modelId ,
149+ prompt : 'Reply with exactly the single word PONG and nothing else.' ,
150+ stream : true ,
151+ maxTokens : 128 ,
152+ temperature : 0 ,
153+ } ,
154+ ( chunk : string ) => {
155+ chunks . push ( chunk ) ;
156+ } ,
157+ ) ;
158+
159+ expect ( chunks . length ) . toBeGreaterThan ( 0 ) ;
160+ expect ( result . content . toLowerCase ( ) ) . toContain ( 'pong' ) ;
161+ expect ( result . usage . output ) . toBeGreaterThan ( 0 ) ;
162+ expect ( result . usage . totalTokens ) . toBeGreaterThan ( 0 ) ;
163+ } ) ;
164+
165+ it ( 'returns token counts for multi-turn chat' , async ( ) => {
166+ const client = new OllamaClient ( baseUrl ) ;
167+ const result = await client . generateWithUsage ( {
168+ model : modelId ,
169+ messages : [
170+ { role : 'user' , content : 'Say hello' } ,
171+ { role : 'assistant' , content : 'Hello!' } ,
172+ { role : 'user' , content : 'Now say goodbye in one word.' } ,
173+ ] ,
174+ maxTokens : 128 ,
175+ temperature : 0 ,
176+ } ) ;
177+
178+ expect ( result . content . length ) . toBeGreaterThan ( 0 ) ;
179+ expect ( result . usage . input ) . toBeGreaterThan ( 0 ) ;
180+ expect ( result . usage . output ) . toBeGreaterThan ( 0 ) ;
181+ } ) ;
182+ } ) ;
183+
121184describeExtended ( 'Ollama live extended' , ( ) => {
122185 jest . setTimeout ( 60_000 ) ;
123186
0 commit comments