fix: correctly pass poe web_search via extra_body when built-in search is enabled (#13434)

Fix #13305 

>
https://creator.poe.com/docs/external-applications/openai-compatible-api#using-custom-parameters-with-extra_body

```js
import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.POE_API_KEY,
    baseURL: "https://api.poe.com/v1",
});

// Example: Using web search and thinking level with Gemini models
const response = await client.chat.completions.create({
    model: "Gemini-3-Pro",
    messages: [{ role: "user", content: "What are the latest developments in quantum computing?" }],
    extra_body: {
        web_search: true,
        thinking_level: "high"
    }
});
```

```release-note
fix(poe): correctly pass poe web_search via extra_body when built-in search is enabled
```
This commit is contained in:
Konv Suu
2026-03-13 17:02:39 +08:00
committed by GitHub
parent 8dd42eb8ba
commit 4aef249151
4 changed files with 76 additions and 5 deletions

View File

@@ -45,7 +45,8 @@ vi.mock('@cherrystudio/ai-core/provider', async (importOriginal) => {
'gateway',
'aihubmix',
'newapi',
'ollama'
'ollama',
'poe'
]
if (customProviders.includes(id)) {
return { success: true, data: id }
@@ -433,6 +434,53 @@ describe('options utils', () => {
})
})
describe('Poe provider', () => {
const poeProvider: Provider = {
id: SystemProviderIds.poe,
name: 'Poe',
type: 'openai',
apiKey: 'test-key',
apiHost: 'https://api.poe.com/v1',
isSystem: true
} as Provider
const poeModel: Model = {
id: 'openai/gpt-4',
name: 'GPT-4',
provider: SystemProviderIds.poe
} as Model
it('should deep merge Poe extra_body reasoning and web search parameters', async () => {
const { getReasoningEffort } = await import('../reasoning')
const { getWebSearchParams } = await import('../websearch')
vi.mocked(getReasoningEffort).mockReturnValue({
extra_body: {
reasoning_effort: 'medium'
}
})
vi.mocked(getWebSearchParams).mockReturnValue({
extra_body: {
web_search: true
}
})
const result = buildProviderOptions(mockAssistant, poeModel, poeProvider, {
enableReasoning: true,
enableWebSearch: true,
enableGenerateImage: false
})
expect(result.providerOptions).toHaveProperty('poe')
expect(result.providerOptions.poe).toMatchObject({
extra_body: {
reasoning_effort: 'medium',
web_search: true
}
})
})
})
describe('Custom parameters', () => {
it('should merge custom provider-specific parameters', async () => {
const { getCustomParameters } = await import('../reasoning')

View File

@@ -68,6 +68,22 @@ describe('websearch utils', () => {
})
})
it('should return extra_body with web_search for poe provider', () => {
const model: Model = {
id: 'Gemini-3-Flash',
name: 'Gemini 3 Flash',
provider: 'poe'
} as Model
const result = getWebSearchParams(model)
expect(result).toEqual({
extra_body: {
web_search: true
}
})
})
it('should return empty object for other providers', () => {
const model: Model = {
id: 'gpt-4',

View File

@@ -40,6 +40,7 @@ import { type AiSdkParam, isAiSdkParam, type OpenAIVerbosity } from '@renderer/t
import { isSupportServiceTierProvider, isSupportVerbosityProvider } from '@renderer/utils/provider'
import type { JSONValue } from 'ai'
import { t } from 'i18next'
import { merge } from 'lodash'
import type { OllamaProviderOptions } from 'ollama-ai-provider-v2'
import { addAnthropicHeaders } from '../prepareParams/header'
@@ -634,10 +635,7 @@ function buildGenericProviderOptions(
if (enableWebSearch) {
const webSearchParams = getWebSearchParams(model)
providerOptions = {
...providerOptions,
...webSearchParams
}
providerOptions = merge({}, providerOptions, webSearchParams)
}
// 特殊处理 Qwen MT

View File

@@ -25,6 +25,15 @@ export function getWebSearchParams(model: Model): Record<string, any> {
}
}
// https://creator.poe.com/docs/external-applications/openai-compatible-api#using-custom-parameters-with-extra_body
if (model.provider === 'poe') {
return {
extra_body: {
web_search: true
}
}
}
if (isOpenAIWebSearchChatCompletionOnlyModel(model)) {
return {
web_search_options: {}