Files
windmill/frontend/src/lib/components/copilot/lib.test.ts
T
centdix fec4008696 fix: preserve ai reasoning content (#9208)
* fix: preserve ai reasoning content

* fix: avoid text-only reasoning replay

* feat: add deepseek ai eval models
2026-05-18 10:40:18 +00:00

118 lines
3.3 KiB
TypeScript

import type {
ChatCompletionChunk,
ChatCompletionMessageFunctionToolCall,
ChatCompletionMessageParam
} from 'openai/resources/index.mjs'
import { describe, expect, it } from 'vitest'
import {
buildAssistantTextMessage,
buildAssistantToolCallMessage,
getReasoningContentDelta
} from './chat/openaiReasoning'
import { getDefaultChatTemperature, modelDisallowsSamplingParams } from './modelConfig'
type AssistantMessageWithReasoning = ChatCompletionMessageParam & {
role: 'assistant'
content?: string
reasoning_content?: string
tool_calls?: ChatCompletionMessageFunctionToolCall[]
}
describe('modelConfig', () => {
it('flags Opus 4.7 model IDs via includes matching', () => {
expect(modelDisallowsSamplingParams('claude-opus-4-7')).toBe(true)
expect(modelDisallowsSamplingParams('claude-opus-4-7@20260416')).toBe(true)
expect(modelDisallowsSamplingParams('claude-opus-4-7/thinking')).toBe(true)
expect(modelDisallowsSamplingParams('anthropic/claude-opus-4-7')).toBe(true)
})
it('omits deterministic temperature for Anthropic Opus 4.7 chat requests', () => {
expect(
getDefaultChatTemperature({ provider: 'anthropic', model: 'claude-opus-4-7' })
).toBeUndefined()
})
it('omits deterministic temperature for non-anthropic providers carrying Opus 4.7 models', () => {
expect(
getDefaultChatTemperature({ provider: 'openrouter', model: 'anthropic/claude-opus-4-7' })
).toBeUndefined()
})
it('keeps deterministic temperature for older Anthropic models', () => {
expect(getDefaultChatTemperature({ provider: 'anthropic', model: 'claude-sonnet-4-6' })).toBe(0)
})
})
describe('openaiReasoning', () => {
it('reads provider-specific reasoning_content deltas', () => {
expect(
getReasoningContentDelta({
reasoning_content: 'thinking'
} as ChatCompletionChunk.Choice.Delta & { reasoning_content: string })
).toBe('thinking')
})
it('preserves DeepSeek reasoning_content on assistant tool-call messages', () => {
const toolCalls: ChatCompletionMessageFunctionToolCall[] = [
{
id: 'call_1',
type: 'function',
function: {
name: 'lookup',
arguments: '{"query":"docs"}'
}
}
]
const assistantMessage = buildAssistantToolCallMessage({
content: 'I will look that up.',
reasoning: {
hasReasoningContent: true,
reasoningContent: 'First, I need a lookup.'
},
toolCalls
}) as AssistantMessageWithReasoning
expect(assistantMessage).toMatchObject({
role: 'assistant',
content: 'I will look that up.',
reasoning_content: 'First, I need a lookup.',
tool_calls: [
{
id: 'call_1',
type: 'function',
function: {
name: 'lookup',
arguments: '{"query":"docs"}'
}
}
]
})
})
it('does not preserve reasoning_content on text-only assistant messages', () => {
expect(buildAssistantTextMessage('done')).toEqual({
role: 'assistant',
content: 'done'
})
})
it('keeps empty reasoning_content when the provider emitted the field', () => {
const assistantMessage = buildAssistantToolCallMessage({
content: '',
reasoning: {
hasReasoningContent: true,
reasoningContent: ''
},
toolCalls: []
}) as AssistantMessageWithReasoning
expect(assistantMessage).toMatchObject({
role: 'assistant',
content: '',
reasoning_content: '',
tool_calls: []
})
})
})