diff --git a/src/background.ts b/src/background.ts index 51709d2..d98957f 100644 --- a/src/background.ts +++ b/src/background.ts @@ -207,7 +207,6 @@ class LLMInvokeHandler { userPrompt: payload.userPrompt, responseFormat: payload.responseFormat === 'text' ? 'text' : 'json', maxTokens: typeof payload.maxTokens === 'number' ? payload.maxTokens : 1024, - temperature: typeof payload.temperature === 'number' ? payload.temperature : 0, }, storedSettings ); diff --git a/src/services/ai.ts b/src/services/ai.ts index a923914..b505403 100644 --- a/src/services/ai.ts +++ b/src/services/ai.ts @@ -30,7 +30,6 @@ export class AIService { userPrompt, responseFormat, maxTokens, - temperature: 0, }; const response = (await chrome.runtime.sendMessage({ diff --git a/src/services/llm/providers.test.ts b/src/services/llm/providers.test.ts new file mode 100644 index 0000000..c643eda --- /dev/null +++ b/src/services/llm/providers.test.ts @@ -0,0 +1,81 @@ +import { describe, expect, it, vi } from 'vitest'; + +const anthropicCreate = vi.hoisted(() => vi.fn()); + +vi.mock('@anthropic-ai/sdk', () => ({ + default: class Anthropic { + messages = { create: anthropicCreate }; + }, +})); + +import { buildOpenAICompatibleRequest, LLMGateway } from './providers'; +import type { LLMInvokePayload } from './types'; + +const payload: LLMInvokePayload = { + systemPrompt: 'system prompt', + userPrompt: 'user prompt', + responseFormat: 'text', + maxTokens: 512, +}; + +describe('buildOpenAICompatibleRequest', () => { + it.each(['gpt-5.6-luna', 'gpt-4.1', 'kimi-k2'])('omits optional parameters for %s', (model) => { + expect(buildOpenAICompatibleRequest(payload, model)).toEqual({ + model, + messages: [ + { role: 'system', content: 'system prompt' }, + { role: 'user', content: 'user prompt' }, + ], + }); + }); + + it('omits temperature from Anthropic Messages requests', async () => { + anthropicCreate.mockResolvedValue({ + id: 'message-1', + content: [{ type: 'text', text: 'response' }], + }); + + await LLMGateway.invoke(payload, { + provider: 'anthropic', + baseUrl: 'https://api.anthropic.com', + apiKey: 'test-key', + model: 'claude-opus-4-6', + }); + + expect(anthropicCreate).toHaveBeenCalledWith({ + model: 'claude-opus-4-6', + max_tokens: 512, + system: 'system prompt', + messages: [{ role: 'user', content: 'user prompt' }], + }); + }); + + it('omits temperature from native custom fetch requests', async () => { + const fetchMock = vi.fn().mockResolvedValue({ + ok: true, + json: async () => ({ message: { content: 'response' } }), + }); + vi.stubGlobal('fetch', fetchMock); + + try { + await LLMGateway.invoke(payload, { + provider: 'custom_fetch', + baseUrl: 'http://localhost:11434', + apiKey: '', + model: 'local-model', + }); + } finally { + vi.unstubAllGlobals(); + } + + const [, options] = fetchMock.mock.calls[0]; + expect(JSON.parse(options.body)).toEqual({ + model: 'local-model', + messages: [ + { role: 'system', content: 'system prompt' }, + { role: 'user', content: 'user prompt' }, + ], + stream: false, + }); + }); +}); diff --git a/src/services/llm/providers.ts b/src/services/llm/providers.ts index 83ad876..387e35d 100644 --- a/src/services/llm/providers.ts +++ b/src/services/llm/providers.ts @@ -12,32 +12,19 @@ import { type OpenAICompatibleRequest = { model: string; messages: Array<{ role: 'system' | 'user'; content: string }>; - max_tokens: number; - temperature?: number; }; export function buildOpenAICompatibleRequest( payload: LLMInvokePayload, model: string ): OpenAICompatibleRequest { - const request: OpenAICompatibleRequest = { + return { model, messages: [ { role: 'system', content: payload.systemPrompt }, { role: 'user', content: payload.userPrompt }, ], - max_tokens: payload.maxTokens, }; - - if (!usesLockedKimiTemperature(model)) { - request.temperature = payload.temperature; - } - - return request; -} - -function usesLockedKimiTemperature(model: string): boolean { - return model.trim().toLowerCase().includes('kimi'); } export class LLMGateway { @@ -112,7 +99,6 @@ export class LLMGateway { const message = await client.messages.create({ model: settings.model, max_tokens: payload.maxTokens, - temperature: payload.temperature, system: payload.systemPrompt, messages: [ { @@ -170,7 +156,6 @@ export class LLMGateway { { role: 'system', content: payload.systemPrompt }, { role: 'user', content: payload.userPrompt }, ], - temperature: payload.temperature, stream: false, } ), diff --git a/src/services/llm/types.ts b/src/services/llm/types.ts index 69eb6b7..5b7fb12 100644 --- a/src/services/llm/types.ts +++ b/src/services/llm/types.ts @@ -7,7 +7,6 @@ export interface LLMInvokePayload { userPrompt: string; responseFormat: LLMResponseFormat; maxTokens: number; - temperature: number; } export interface LLMInvokeResult {