diff --git a/packages/core/src/core/openaiContentGenerator/converter.test.ts b/packages/core/src/core/openaiContentGenerator/converter.test.ts index 91418e07b1..cad4777096 100644 --- a/packages/core/src/core/openaiContentGenerator/converter.test.ts +++ b/packages/core/src/core/openaiContentGenerator/converter.test.ts @@ -3816,97 +3816,6 @@ describe('OpenAIContentConverter', () => { ]); }); - it('should convert GLM inline content to thought parts', () => { - const response = converter.convertOpenAIResponseToGemini( - { - object: 'chat.completion', - id: 'chatcmpl-glm-1', - created: 123, - model: 'glm-5.2', - choices: [ - { - index: 0, - message: { - role: 'assistant', - reasoning_content: '', - content: - 'The user is asking a simple logic puzzle.LEAK_CHECK_FINAL: prize is in B', - }, - finish_reason: 'stop', - logprobs: null, - }, - ], - } as unknown as OpenAI.Chat.ChatCompletion, - withTaggedThinkingOptions(), - ); - - expect(response.candidates?.[0]?.content?.parts).toEqual([ - { - text: 'The user is asking a simple logic puzzle.', - thought: true, - }, - { text: 'LEAK_CHECK_FINAL: prize is in B' }, - ]); - }); - - it('should preserve reasoning_content when tagged parsing finds no thinking tags', () => { - const response = converter.convertOpenAIResponseToGemini( - { - object: 'chat.completion', - id: 'chatcmpl-glm-2', - created: 123, - model: 'glm-5.2', - choices: [ - { - index: 0, - message: { - role: 'assistant', - reasoning_content: 'separate reasoning channel', - content: 'final answer', - }, - finish_reason: 'stop', - logprobs: null, - }, - ], - } as unknown as OpenAI.Chat.ChatCompletion, - withTaggedThinkingOptions(), - ); - - expect(response.candidates?.[0]?.content?.parts).toEqual([ - { text: 'separate reasoning channel', thought: true }, - { text: 'final answer' }, - ]); - }); - - it('should not duplicate reasoning_content when content already has tagged thinking', () => { - const response = converter.convertOpenAIResponseToGemini( - { - object: 'chat.completion', - id: 'chatcmpl-glm-3', - created: 123, - model: 'glm-5.2', - choices: [ - { - index: 0, - message: { - role: 'assistant', - reasoning_content: 'duplicate reasoning channel', - content: 'tagged reasoningfinal answer', - }, - finish_reason: 'stop', - logprobs: null, - }, - ], - } as unknown as OpenAI.Chat.ChatCompletion, - withTaggedThinkingOptions(), - ); - - expect(response.candidates?.[0]?.content?.parts).toEqual([ - { text: 'tagged reasoning', thought: true }, - { text: 'final answer' }, - ]); - }); - it('should preserve ordering around blocks', () => { const response = converter.convertOpenAIResponseToGemini( { @@ -4085,335 +3994,6 @@ describe('OpenAIContentConverter', () => { ]); }); - it('should suppress reasoning_content when the same streaming chunk has tagged thinking content', () => { - const context = withTaggedThinkingStreamParser(); - - const chunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-dual-tagged', - created: 456, - choices: [ - { - index: 0, - delta: { - reasoning_content: 'duplicate reasoning channel', - content: 'tagged reasoningfinal answer', - }, - finish_reason: 'stop', - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(chunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'tagged reasoning', thought: true }, - { text: 'final answer' }, - ]); - }); - - it('should suppress late reasoning_content after streaming tagged thinking content', () => { - const context = withTaggedThinkingStreamParser(); - - const firstChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-late-reasoning-1', - created: 456, - choices: [ - { - index: 0, - delta: { content: 'tagged reasoning' }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const secondChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-late-reasoning-2', - created: 457, - choices: [ - { - index: 0, - delta: { reasoning_content: 'late reasoning' }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(firstChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'tagged reasoning', thought: true }, - ]); - expect(secondChunk.candidates?.[0]?.content?.parts).toEqual([]); - }); - - it('should suppress buffered reasoning_content when later streaming content has tagged thinking', () => { - const context = withTaggedThinkingStreamParser(); - - const firstChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-reasoning-1', - created: 456, - choices: [ - { - index: 0, - delta: { reasoning_content: 'duplicate reasoning channel' }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const secondChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-reasoning-2', - created: 457, - choices: [ - { - index: 0, - delta: { content: 'tagged reasoning' }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const finalChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-reasoning-3', - created: 458, - choices: [ - { - index: 0, - delta: { content: 'final answer' }, - finish_reason: 'stop', - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(firstChunk.candidates?.[0]?.content?.parts).toEqual([]); - expect(secondChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'tagged reasoning', thought: true }, - ]); - expect(finalChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'final answer' }, - ]); - }); - - it('should flush buffered content before later tagged thinking content', () => { - const context = withTaggedThinkingStreamParser(); - - const firstChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-content-before-tag-1', - created: 456, - choices: [ - { - index: 0, - delta: { - reasoning_content: 'duplicate reasoning channel', - content: 'early visible ', - }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const secondChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-content-before-tag-2', - created: 457, - choices: [ - { - index: 0, - delta: { content: 'tagged reasoningfinal answer' }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(firstChunk.candidates?.[0]?.content?.parts).toEqual([]); - expect(secondChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'early visible ' }, - { text: 'tagged reasoning', thought: true }, - { text: 'final answer' }, - ]); - }); - - it('should flush buffered content before current content when reasoning flushes on finish', () => { - const context = withTaggedThinkingStreamParser(); - - const firstChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-content-order-1', - created: 456, - choices: [ - { - index: 0, - delta: { - reasoning_content: 'step 1', - content: 'hello ', - }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const finalChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-buffered-content-order-2', - created: 457, - choices: [ - { - index: 0, - delta: { content: 'world' }, - finish_reason: 'stop', - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(firstChunk.candidates?.[0]?.content?.parts).toEqual([]); - expect(finalChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'step 1', thought: true }, - { text: 'hello ' }, - { text: 'world' }, - ]); - }); - - it('should flush buffered reasoning_content when tagged streaming content has no thinking tags', () => { - const context = withTaggedThinkingStreamParser(); - - const firstChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-reasoning-only-1', - created: 456, - choices: [ - { - index: 0, - delta: { - reasoning_content: 'separate reasoning channel', - content: 'final ', - }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const finalChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-reasoning-only-2', - created: 457, - choices: [ - { - index: 0, - delta: { content: 'answer' }, - finish_reason: 'stop', - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(firstChunk.candidates?.[0]?.content?.parts).toEqual([]); - expect(finalChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'separate reasoning channel', thought: true }, - { text: 'final ' }, - { text: 'answer' }, - ]); - }); - - it('should flush reasoning-only chunks when tagged streaming content has no thinking tags', () => { - const context = withTaggedThinkingStreamParser(); - - const firstChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-reasoning-only-no-content-1', - created: 456, - choices: [ - { - index: 0, - delta: { reasoning_content: 'step 1' }, - finish_reason: null, - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - const finalChunk = converter.convertOpenAIChunkToGemini( - { - object: 'chat.completion.chunk', - id: 'chunk-glm-reasoning-only-no-content-2', - created: 457, - choices: [ - { - index: 0, - delta: {}, - finish_reason: 'stop', - logprobs: null, - }, - ], - model: 'glm-5.2', - } as unknown as OpenAI.Chat.ChatCompletionChunk, - context, - ); - - expect(firstChunk.candidates?.[0]?.content?.parts).toEqual([]); - expect(finalChunk.candidates?.[0]?.content?.parts).toEqual([ - { text: 'step 1', thought: true }, - ]); - }); - it('should flush unclosed streaming thinking content on finish', () => { const context = withTaggedThinkingStreamParser(); diff --git a/packages/core/src/core/openaiContentGenerator/converter.ts b/packages/core/src/core/openaiContentGenerator/converter.ts index 33bd88be0c..633b478093 100644 --- a/packages/core/src/core/openaiContentGenerator/converter.ts +++ b/packages/core/src/core/openaiContentGenerator/converter.ts @@ -1081,10 +1081,6 @@ function convertOpenAITextToParts( return parseTaggedThinkingText(text); } -function hasThoughtPart(parts: Part[]): boolean { - return parts.some((part) => part.thought === true); -} - /** * Convert OpenAI response to Gemini format. */ @@ -1097,23 +1093,26 @@ export function convertOpenAIResponseToGemini( if (choice) { const parts: Part[] = []; - const textParts = choice.message.content - ? convertOpenAITextToParts(choice.message.content, requestContext) - : []; // Handle reasoning content (thoughts). - // Tagged thinking providers may put thoughts in content, while other - // responses still use reasoning_content. Preserve the separate reasoning - // channel unless content parsing already produced thought parts. - const reasoningText = - (choice.message as ExtendedCompletionMessage).reasoning_content ?? - (choice.message as ExtendedCompletionMessage).reasoning; - if (reasoningText && !hasThoughtPart(textParts)) { - parts.push({ text: reasoningText, thought: true }); + // When taggedThinkingTags is enabled, thought content is already + // extracted from the text content via convertOpenAITextToParts. + // Skip reasoning_content extraction to avoid duplicating thought parts. + if (!requestContext.responseParsingOptions?.taggedThinkingTags) { + const reasoningText = + (choice.message as ExtendedCompletionMessage).reasoning_content ?? + (choice.message as ExtendedCompletionMessage).reasoning; + if (reasoningText) { + parts.push({ text: reasoningText, thought: true }); + } } // Handle text content - parts.push(...textParts); + if (choice.message.content) { + parts.push( + ...convertOpenAITextToParts(choice.message.content, requestContext), + ); + } // Handle tool calls if (choice.message.tool_calls) { @@ -1225,12 +1224,29 @@ export function convertOpenAIChunkToGemini( if (choice) { const parts: Part[] = []; - let contentParts: Part[] = []; // Handle reasoning content (thoughts). - const reasoningText = - (choice.delta as ExtendedCompletionChunkDelta)?.reasoning_content ?? - (choice.delta as ExtendedCompletionChunkDelta)?.reasoning; + // When taggedThinkingTags is enabled, thought content is already + // extracted from the text content via convertOpenAITextToParts. + // Skip reasoning_content extraction to avoid duplicating thought parts. + if (!requestContext.responseParsingOptions?.taggedThinkingTags) { + const reasoningText = + (choice.delta as ExtendedCompletionChunkDelta)?.reasoning_content ?? + (choice.delta as ExtendedCompletionChunkDelta)?.reasoning; + if (reasoningText) { + const normalizedReasoningText = normalizeStreamingTextDelta( + reasoningText, + (requestContext.reasoningDeltaState ??= { + emittedText: '', + emittedLength: 0, + cumulativeMode: false, + }), + ); + if (normalizedReasoningText) { + parts.push({ text: normalizedReasoningText, thought: true }); + } + } + } // Handle text content if (typeof choice.delta?.content === 'string') { @@ -1245,99 +1261,19 @@ export function convertOpenAIChunkToGemini( // Skip empty-string push mid-stream; still call on finish_reason to // flush any buffered tagged-thinking content. if (normalizedContent || choice.finish_reason) { - contentParts = convertOpenAITextToParts( - normalizedContent, - requestContext, - Boolean(choice.finish_reason), + parts.push( + ...convertOpenAITextToParts( + normalizedContent, + requestContext, + Boolean(choice.finish_reason), + ), ); } } else if (choice.finish_reason) { // Flush any buffered tagged-thinking content on stream end - contentParts = convertOpenAITextToParts('', requestContext, true); + parts.push(...convertOpenAITextToParts('', requestContext, true)); } - if (hasThoughtPart(contentParts)) { - requestContext.hasTaggedThinkingThought = true; - requestContext.pendingReasoningText = undefined; - debugLogger.debug( - 'convertOpenAIChunkToGemini: tagged thinking content emitted a thought; dropping buffered reasoning', - ); - if (requestContext.pendingContentParts?.length) { - debugLogger.debug( - `convertOpenAIChunkToGemini: flushing ${requestContext.pendingContentParts.length} buffered content part(s) before tagged content`, - ); - parts.push(...requestContext.pendingContentParts); - requestContext.pendingContentParts = undefined; - } - } - - if ( - reasoningText && - (!requestContext.responseParsingOptions?.taggedThinkingTags || - !requestContext.hasTaggedThinkingThought) - ) { - const normalizedReasoningText = normalizeStreamingTextDelta( - reasoningText, - (requestContext.reasoningDeltaState ??= { - emittedText: '', - emittedLength: 0, - cumulativeMode: false, - }), - ); - if ( - normalizedReasoningText && - !requestContext.responseParsingOptions?.taggedThinkingTags - ) { - parts.push({ text: normalizedReasoningText, thought: true }); - } else if ( - normalizedReasoningText && - !requestContext.hasTaggedThinkingThought - ) { - requestContext.pendingReasoningText = - (requestContext.pendingReasoningText ?? '') + normalizedReasoningText; - debugLogger.debug( - `convertOpenAIChunkToGemini: buffered reasoning text (${requestContext.pendingReasoningText.length} chars) for tagged stream`, - ); - } - } - - if ( - requestContext.responseParsingOptions?.taggedThinkingTags && - !requestContext.hasTaggedThinkingThought && - requestContext.pendingReasoningText && - contentParts.length - ) { - requestContext.pendingContentParts = [ - ...(requestContext.pendingContentParts ?? []), - ...contentParts, - ]; - debugLogger.debug( - `convertOpenAIChunkToGemini: buffered ${contentParts.length} content part(s) behind pending reasoning`, - ); - contentParts = []; - } - - if ( - choice.finish_reason && - requestContext.responseParsingOptions?.taggedThinkingTags && - !requestContext.hasTaggedThinkingThought && - requestContext.pendingReasoningText - ) { - debugLogger.debug( - 'convertOpenAIChunkToGemini: flushing buffered reasoning for tagged stream with no tagged thought', - ); - parts.push({ text: requestContext.pendingReasoningText, thought: true }); - requestContext.pendingReasoningText = undefined; - } - if (choice.finish_reason && requestContext.pendingContentParts?.length) { - debugLogger.debug( - `convertOpenAIChunkToGemini: flushing ${requestContext.pendingContentParts.length} buffered content part(s) on stream finish`, - ); - parts.push(...requestContext.pendingContentParts); - requestContext.pendingContentParts = undefined; - } - parts.push(...contentParts); - // Handle tool calls using the stream-local parser if (choice.delta?.tool_calls) { for (const toolCall of choice.delta.tool_calls) { diff --git a/packages/core/src/core/openaiContentGenerator/pipeline.test.ts b/packages/core/src/core/openaiContentGenerator/pipeline.test.ts index 9aca5a51be..00d83272fa 100644 --- a/packages/core/src/core/openaiContentGenerator/pipeline.test.ts +++ b/packages/core/src/core/openaiContentGenerator/pipeline.test.ts @@ -268,44 +268,6 @@ describe('ContentGenerationPipeline', () => { ); }); - it('should request provider parsing options for the effective request model', async () => { - const request: GenerateContentParameters = { - model: 'glm-5.2', - contents: [{ parts: [{ text: 'Hello' }], role: 'user' }], - }; - const mockOpenAIResponse = { - id: 'response-id', - choices: [{ message: { content: 'response' }, finish_reason: 'stop' }], - created: Date.now(), - model: 'glm-5.2', - } as OpenAI.Chat.ChatCompletion; - const mockGeminiResponse = new GenerateContentResponse(); - - mockProvider.getResponseParsingOptions = vi.fn().mockReturnValue({ - taggedThinkingTags: true, - }); - (mockConverter.convertGeminiRequestToOpenAI as Mock).mockReturnValue([]); - (mockConverter.convertOpenAIResponseToGemini as Mock).mockReturnValue( - mockGeminiResponse, - ); - (mockClient.chat.completions.create as Mock).mockResolvedValue( - mockOpenAIResponse, - ); - - await pipeline.execute(request, 'prompt-id'); - - expect(mockProvider.getResponseParsingOptions).toHaveBeenCalledWith( - 'glm-5.2', - ); - expect(mockConverter.convertOpenAIResponseToGemini).toHaveBeenCalledWith( - mockOpenAIResponse, - expect.objectContaining({ - model: 'glm-5.2', - responseParsingOptions: { taggedThinkingTags: true }, - }), - ); - }); - it('should let provider request context overrides take precedence over content generator config', async () => { const request: GenerateContentParameters = { model: 'test-model', diff --git a/packages/core/src/core/openaiContentGenerator/pipeline.ts b/packages/core/src/core/openaiContentGenerator/pipeline.ts index 154c366ab9..1debfc2f46 100644 --- a/packages/core/src/core/openaiContentGenerator/pipeline.ts +++ b/packages/core/src/core/openaiContentGenerator/pipeline.ts @@ -781,7 +781,7 @@ export class ContentGenerationPipeline { ? new StreamingToolCallParser() : undefined; const responseParsingOptions = - this.config.provider.getResponseParsingOptions?.(effectiveModel); + this.config.provider.getResponseParsingOptions?.(); const taggedThinkingParser = isStreaming && responseParsingOptions?.taggedThinkingTags ? new TaggedThinkingParser() diff --git a/packages/core/src/core/openaiContentGenerator/provider/dashscope.test.ts b/packages/core/src/core/openaiContentGenerator/provider/dashscope.test.ts index 4a1599fcbd..7cdbb1eb8b 100644 --- a/packages/core/src/core/openaiContentGenerator/provider/dashscope.test.ts +++ b/packages/core/src/core/openaiContentGenerator/provider/dashscope.test.ts @@ -108,49 +108,6 @@ describe('DashScopeOpenAICompatibleProvider', () => { }); }); - describe('getResponseParsingOptions', () => { - it('should enable tagged thinking parsing for GLM models', () => { - const glmProvider = new DashScopeOpenAICompatibleProvider( - { ...mockContentGeneratorConfig, model: 'glm-5.2' }, - mockCliConfig, - ); - - expect(glmProvider.getResponseParsingOptions()).toEqual({ - taggedThinkingTags: true, - }); - }); - - it('should match GLM models case-insensitively', () => { - const glmProvider = new DashScopeOpenAICompatibleProvider( - { ...mockContentGeneratorConfig, model: 'GLM-5.1' }, - mockCliConfig, - ); - - expect(glmProvider.getResponseParsingOptions()).toEqual({ - taggedThinkingTags: true, - }); - }); - - it('should use the request model override when provided', () => { - expect(provider.getResponseParsingOptions('glm-5.2')).toEqual({ - taggedThinkingTags: true, - }); - }); - - it('should let a non-GLM request model override a configured GLM model', () => { - const glmProvider = new DashScopeOpenAICompatibleProvider( - { ...mockContentGeneratorConfig, model: 'glm-5.2' }, - mockCliConfig, - ); - - expect(glmProvider.getResponseParsingOptions('qwen-max')).toEqual({}); - }); - - it('should not enable tagged thinking parsing for non-GLM models', () => { - expect(provider.getResponseParsingOptions()).toEqual({}); - }); - }); - describe('isDashScopeProvider', () => { it('should return true for QWEN_OAUTH auth type', () => { const config = { diff --git a/packages/core/src/core/openaiContentGenerator/provider/dashscope.ts b/packages/core/src/core/openaiContentGenerator/provider/dashscope.ts index 3fc35cd1a7..d285173cb3 100644 --- a/packages/core/src/core/openaiContentGenerator/provider/dashscope.ts +++ b/packages/core/src/core/openaiContentGenerator/provider/dashscope.ts @@ -15,7 +15,6 @@ import type { ChatCompletionContentPartWithCache, ChatCompletionToolWithCache, } from './types.js'; -import type { OpenAIResponseParsingOptions } from '../responseParsingOptions.js'; import { buildRuntimeFetchOptions } from '../../../utils/runtimeFetchOptions.js'; import { createDebugLogger } from '../../../utils/debugLogger.js'; import { DefaultOpenAICompatibleProvider } from './default.js'; @@ -314,13 +313,6 @@ export class DashScopeOpenAICompatibleProvider extends DefaultOpenAICompatiblePr return {}; } - getResponseParsingOptions(model?: string): OpenAIResponseParsingOptions { - if (this.isGlmModel(model ?? this.contentGeneratorConfig.model)) { - return { taggedThinkingTags: true }; - } - return {}; - } - /** * Add cache control flag to specified message(s) for DashScope providers */ diff --git a/packages/core/src/core/openaiContentGenerator/provider/types.ts b/packages/core/src/core/openaiContentGenerator/provider/types.ts index 85332a4463..f70f9fcd13 100644 --- a/packages/core/src/core/openaiContentGenerator/provider/types.ts +++ b/packages/core/src/core/openaiContentGenerator/provider/types.ts @@ -31,7 +31,7 @@ export interface OpenAICompatibleProvider { userPromptId: string, ): OpenAI.Chat.ChatCompletionCreateParams; getDefaultGenerationConfig(): GenerateContentConfig; - getResponseParsingOptions?(model?: string): OpenAIResponseParsingOptions; + getResponseParsingOptions?(): OpenAIResponseParsingOptions; getRequestContextOverrides?(): OpenAIRequestContextOverrides; } diff --git a/packages/core/src/core/openaiContentGenerator/types.ts b/packages/core/src/core/openaiContentGenerator/types.ts index 53d28d6635..6a57235f5a 100644 --- a/packages/core/src/core/openaiContentGenerator/types.ts +++ b/packages/core/src/core/openaiContentGenerator/types.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { GenerateContentParameters, Part } from '@google/genai'; +import type { GenerateContentParameters } from '@google/genai'; import type { Config } from '../../config/config.js'; import type { ContentGeneratorConfig, @@ -63,25 +63,6 @@ export interface RequestContext { * channel are deduplicated correctly. */ reasoningDeltaState?: StreamingTextDeltaState; - /** - * Set once tagged content parsing emits a thought in this stream. Used to - * suppress duplicate provider reasoning-channel output that arrives in a - * different chunk. - */ - hasTaggedThinkingThought?: boolean; - /** - * Reasoning-channel text buffered while a tagged-thinking stream is still - * open. It is emitted only if the stream finishes without tagged content - * producing any thought parts. If a stream ends abnormally before a finish - * chunk, buffered reasoning is best-effort and may be lost. - */ - pendingReasoningText?: string; - /** - * Visible content buffered behind pending reasoning-channel text while a - * tagged-thinking stream is still ambiguous. This preserves thought-before- - * answer ordering when the provider uses reasoning_content without tags. - */ - pendingContentParts?: Part[]; } export interface ErrorHandler {