@@ -17,6 +17,7 @@ import { DashScopeOpenAICompatibleProvider } from './dashscope.js';
1717import type { Config } from '../../../config/config.js' ;
1818import type { ContentGeneratorConfig } from '../../contentGenerator.js' ;
1919import { AuthType } from '../../contentGenerator.js' ;
20+ import type { ChatCompletionToolWithCache } from './types.js' ;
2021import { DEFAULT_TIMEOUT , DEFAULT_MAX_RETRIES } from '../constants.js' ;
2122
2223// Mock OpenAI
@@ -253,17 +254,110 @@ describe('DashScopeOpenAICompatibleProvider', () => {
253254 } ,
254255 ] ) ;
255256
256- // Last message should NOT have cache control for non-streaming
257+ // Last message should NOT have cache control for non-streaming requests
257258 const lastMessage = result . messages [ 1 ] ;
258259 expect ( lastMessage . role ) . toBe ( 'user' ) ;
259260 expect ( lastMessage . content ) . toBe ( 'Hello!' ) ;
260261 } ) ;
261262
262- it ( 'should add cache control to both system and last messages for streaming requests' , ( ) => {
263+ it ( 'should add cache control to system message only for non-streaming requests with tools' , ( ) => {
264+ const requestWithTool : OpenAI . Chat . ChatCompletionCreateParams = {
265+ ...baseRequest ,
266+ messages : [
267+ { role : 'system' , content : 'You are a helpful assistant.' } ,
268+ {
269+ role : 'tool' ,
270+ content : 'First tool output' ,
271+ tool_call_id : 'call_1' ,
272+ } ,
273+ {
274+ role : 'tool' ,
275+ content : 'Second tool output' ,
276+ tool_call_id : 'call_2' ,
277+ } ,
278+ { role : 'user' , content : 'Hello!' } ,
279+ ] ,
280+ tools : [
281+ {
282+ type : 'function' ,
283+ function : {
284+ name : 'mockTool' ,
285+ parameters : { type : 'object' , properties : { } } ,
286+ } ,
287+ } ,
288+ ] ,
289+ stream : false ,
290+ } ;
291+
292+ const result = provider . buildRequest ( requestWithTool , 'test-prompt-id' ) ;
293+
294+ expect ( result . messages ) . toHaveLength ( 4 ) ;
295+
296+ const systemMessage = result . messages [ 0 ] ;
297+ expect ( systemMessage . content ) . toEqual ( [
298+ {
299+ type : 'text' ,
300+ text : 'You are a helpful assistant.' ,
301+ cache_control : { type : 'ephemeral' } ,
302+ } ,
303+ ] ) ;
304+
305+ // Tool messages should remain unchanged
306+ const firstToolMessage = result . messages [ 1 ] ;
307+ expect ( firstToolMessage . role ) . toBe ( 'tool' ) ;
308+ expect ( firstToolMessage . content ) . toBe ( 'First tool output' ) ;
309+
310+ const secondToolMessage = result . messages [ 2 ] ;
311+ expect ( secondToolMessage . role ) . toBe ( 'tool' ) ;
312+ expect ( secondToolMessage . content ) . toBe ( 'Second tool output' ) ;
313+
314+ // Last message should NOT have cache control for non-streaming requests
315+ const lastMessage = result . messages [ 3 ] ;
316+ expect ( lastMessage . role ) . toBe ( 'user' ) ;
317+ expect ( lastMessage . content ) . toBe ( 'Hello!' ) ;
318+
319+ // Tools should NOT have cache control for non-streaming requests
320+ const tools = result . tools as ChatCompletionToolWithCache [ ] ;
321+ expect ( tools ) . toBeDefined ( ) ;
322+ expect ( tools ) . toHaveLength ( 1 ) ;
323+ expect ( tools [ 0 ] . cache_control ) . toBeUndefined ( ) ;
324+ } ) ;
325+
326+ it ( 'should add cache control to system, last history message, and last tool definition for streaming requests' , ( ) => {
263327 const request = { ...baseRequest , stream : true } ;
264- const result = provider . buildRequest ( request , 'test-prompt-id' ) ;
328+ const requestWithToolMessage : OpenAI . Chat . ChatCompletionCreateParams = {
329+ ...request ,
330+ messages : [
331+ { role : 'system' , content : 'You are a helpful assistant.' } ,
332+ {
333+ role : 'tool' ,
334+ content : 'First tool output' ,
335+ tool_call_id : 'call_1' ,
336+ } ,
337+ {
338+ role : 'tool' ,
339+ content : 'Second tool output' ,
340+ tool_call_id : 'call_2' ,
341+ } ,
342+ { role : 'user' , content : 'Hello!' } ,
343+ ] ,
344+ tools : [
345+ {
346+ type : 'function' ,
347+ function : {
348+ name : 'mockTool' ,
349+ parameters : { type : 'object' , properties : { } } ,
350+ } ,
351+ } ,
352+ ] ,
353+ } ;
265354
266- expect ( result . messages ) . toHaveLength ( 2 ) ;
355+ const result = provider . buildRequest (
356+ requestWithToolMessage ,
357+ 'test-prompt-id' ,
358+ ) ;
359+
360+ expect ( result . messages ) . toHaveLength ( 4 ) ;
267361
268362 // System message should have cache control
269363 const systemMessage = result . messages [ 0 ] ;
@@ -275,15 +369,58 @@ describe('DashScopeOpenAICompatibleProvider', () => {
275369 } ,
276370 ] ) ;
277371
278- // Last message should also have cache control for streaming
279- const lastMessage = result . messages [ 1 ] ;
372+ // Tool messages should remain unchanged
373+ const firstToolMessage = result . messages [ 1 ] ;
374+ expect ( firstToolMessage . role ) . toBe ( 'tool' ) ;
375+ expect ( firstToolMessage . content ) . toBe ( 'First tool output' ) ;
376+
377+ const secondToolMessage = result . messages [ 2 ] ;
378+ expect ( secondToolMessage . role ) . toBe ( 'tool' ) ;
379+ expect ( secondToolMessage . content ) . toBe ( 'Second tool output' ) ;
380+
381+ // Last message should also have cache control
382+ const lastMessage = result . messages [ 3 ] ;
280383 expect ( lastMessage . content ) . toEqual ( [
281384 {
282385 type : 'text' ,
283386 text : 'Hello!' ,
284387 cache_control : { type : 'ephemeral' } ,
285388 } ,
286389 ] ) ;
390+
391+ const tools = result . tools as ChatCompletionToolWithCache [ ] ;
392+ expect ( tools ) . toBeDefined ( ) ;
393+ expect ( tools ) . toHaveLength ( 1 ) ;
394+ expect ( tools [ 0 ] . cache_control ) . toEqual ( { type : 'ephemeral' } ) ;
395+ } ) ;
396+
397+ it ( 'should not add cache control to tool messages when request.tools is undefined' , ( ) => {
398+ const requestWithoutConfiguredTools : OpenAI . Chat . ChatCompletionCreateParams =
399+ {
400+ ...baseRequest ,
401+ messages : [
402+ { role : 'system' , content : 'You are a helpful assistant.' } ,
403+ {
404+ role : 'tool' ,
405+ content : 'Tool output' ,
406+ tool_call_id : 'call_1' ,
407+ } ,
408+ { role : 'user' , content : 'Hello!' } ,
409+ ] ,
410+ } ;
411+
412+ const result = provider . buildRequest (
413+ requestWithoutConfiguredTools ,
414+ 'test-prompt-id' ,
415+ ) ;
416+
417+ expect ( result . messages ) . toHaveLength ( 3 ) ;
418+
419+ const toolMessage = result . messages [ 1 ] ;
420+ expect ( toolMessage . role ) . toBe ( 'tool' ) ;
421+ expect ( toolMessage . content ) . toBe ( 'Tool output' ) ;
422+
423+ expect ( result . tools ) . toBeUndefined ( ) ;
287424 } ) ;
288425
289426 it ( 'should include metadata in the request' , ( ) => {
0 commit comments