11import { describe , expect , test , beforeEach , afterEach } from 'bun:test'
2- import { isOpenAIThinkingEnabled } from '../index.js'
2+ import { isOpenAIThinkingEnabled , buildOpenAIRequestBody } from '../index.js'
33
44describe ( 'isOpenAIThinkingEnabled' , ( ) => {
55 const originalEnv = {
@@ -12,8 +12,13 @@ describe('isOpenAIThinkingEnabled', () => {
1212 } )
1313
1414 afterEach ( ( ) => {
15- // Restore original env var
16- process . env . OPENAI_ENABLE_THINKING = originalEnv . OPENAI_ENABLE_THINKING
15+ // Restore original env var — delete key if it was originally undefined
16+ // to avoid leaking the env key into subsequent tests
17+ if ( originalEnv . OPENAI_ENABLE_THINKING === undefined ) {
18+ delete process . env . OPENAI_ENABLE_THINKING
19+ } else {
20+ process . env . OPENAI_ENABLE_THINKING = originalEnv . OPENAI_ENABLE_THINKING
21+ }
1722 } )
1823
1924 describe ( 'OPENAI_ENABLE_THINKING env var' , ( ) => {
@@ -140,53 +145,82 @@ describe('isOpenAIThinkingEnabled', () => {
140145 } )
141146} )
142147
143- describe ( 'thinking request parameters' , ( ) => {
144- // Note: These tests verify the request body structure indirectly.
145- // The actual API call is mocked in integration tests.
146- // Here we document the expected parameter formats:
148+ describe ( 'buildOpenAIRequestBody — thinking params' , ( ) => {
149+ const baseParams = {
150+ model : 'deepseek-reasoner' ,
151+ messages : [ { role : 'user' , content : 'hello' } ] ,
152+ tools : [ ] as any [ ] ,
153+ toolChoice : undefined as any ,
154+ }
147155
148- test ( 'documents official DeepSeek API format: thinking: { type: "enabled" }' , ( ) => {
149- // Official DeepSeek API expects:
150- const officialFormat = {
151- thinking : { type : 'enabled' } ,
152- }
153- expect ( officialFormat . thinking . type ) . toBe ( 'enabled' )
156+ test ( 'includes official DeepSeek API thinking format when enabled' , ( ) => {
157+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : true } )
158+ expect ( body . thinking ) . toEqual ( { type : 'enabled' } )
154159 } )
155160
156- test ( 'documents vLLM/self-hosted format: enable_thinking + chat_template_kwargs' , ( ) => {
157- // Self-hosted DeepSeek-V3.2/vLLM expects:
158- const vllmFormat = {
159- enable_thinking : true ,
160- chat_template_kwargs : { thinking : true } ,
161- }
162- expect ( vllmFormat . enable_thinking ) . toBe ( true )
163- expect ( vllmFormat . chat_template_kwargs . thinking ) . toBe ( true )
161+ test ( 'includes vLLM/self-hosted thinking format when enabled' , ( ) => {
162+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : true } )
163+ expect ( body . enable_thinking ) . toBe ( true )
164+ expect ( body . chat_template_kwargs ) . toEqual ( { thinking : true } )
164165 } )
165166
166- test ( 'both formats are added simultaneously when thinking is enabled' , ( ) => {
167- // The implementation adds both formats so each endpoint
168- // can use the one it recognizes:
169- const combinedFormat = {
170- // Official DeepSeek API format
171- thinking : { type : 'enabled' } ,
172- // Self-hosted DeepSeek-V3.2/vLLM format
173- enable_thinking : true ,
174- chat_template_kwargs : { thinking : true } ,
175- }
176- expect ( combinedFormat . thinking . type ) . toBe ( 'enabled' )
177- expect ( combinedFormat . enable_thinking ) . toBe ( true )
178- expect ( combinedFormat . chat_template_kwargs . thinking ) . toBe ( true )
167+ test ( 'includes both formats simultaneously when enabled' , ( ) => {
168+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : true } )
169+ expect ( body . thinking ) . toEqual ( { type : 'enabled' } )
170+ expect ( body . enable_thinking ) . toBe ( true )
171+ expect ( body . chat_template_kwargs . thinking ) . toBe ( true )
179172 } )
180173
181- test ( 'thinking params are NOT added when thinking is disabled' , ( ) => {
182- // When thinking is disabled, none of these params should be present:
183- const disabledFormat = {
184- model : 'gpt-4o' ,
185- messages : [ ] ,
186- stream : true ,
187- }
188- expect ( ( disabledFormat as any ) . thinking ) . toBeUndefined ( )
189- expect ( ( disabledFormat as any ) . enable_thinking ) . toBeUndefined ( )
190- expect ( ( disabledFormat as any ) . chat_template_kwargs ) . toBeUndefined ( )
174+ test ( 'does NOT include thinking params when disabled' , ( ) => {
175+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : false } )
176+ expect ( body . thinking ) . toBeUndefined ( )
177+ expect ( body . enable_thinking ) . toBeUndefined ( )
178+ expect ( body . chat_template_kwargs ) . toBeUndefined ( )
179+ } )
180+
181+ test ( 'always includes stream and stream_options' , ( ) => {
182+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : false } )
183+ expect ( body . stream ) . toBe ( true )
184+ expect ( body . stream_options ) . toEqual ( { include_usage : true } )
185+ } )
186+
187+ test ( 'includes temperature when thinking is off and override is set' , ( ) => {
188+ const body = buildOpenAIRequestBody ( {
189+ ...baseParams ,
190+ enableThinking : false ,
191+ temperatureOverride : 0.7 ,
192+ } )
193+ expect ( body . temperature ) . toBe ( 0.7 )
194+ } )
195+
196+ test ( 'excludes temperature when thinking is on even if override is set' , ( ) => {
197+ const body = buildOpenAIRequestBody ( {
198+ ...baseParams ,
199+ enableThinking : true ,
200+ temperatureOverride : 0.7 ,
201+ } )
202+ expect ( body . temperature ) . toBeUndefined ( )
203+ } )
204+
205+ test ( 'excludes temperature when thinking is off and no override' , ( ) => {
206+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : false } )
207+ expect ( body . temperature ) . toBeUndefined ( )
208+ } )
209+
210+ test ( 'includes tools and tool_choice when tools are provided' , ( ) => {
211+ const body = buildOpenAIRequestBody ( {
212+ ...baseParams ,
213+ tools : [ { type : 'function' , function : { name : 'test' } } ] ,
214+ toolChoice : 'auto' ,
215+ enableThinking : false ,
216+ } )
217+ expect ( body . tools ) . toHaveLength ( 1 )
218+ expect ( body . tool_choice ) . toBe ( 'auto' )
219+ } )
220+
221+ test ( 'excludes tools when empty' , ( ) => {
222+ const body = buildOpenAIRequestBody ( { ...baseParams , enableThinking : false } )
223+ expect ( body . tools ) . toBeUndefined ( )
224+ expect ( body . tool_choice ) . toBeUndefined ( )
191225 } )
192226} )
0 commit comments