fix: keep streamed reasoning expanded
This commit is contained in:
@@ -453,6 +453,92 @@ describe('ModelAgentRuntime', () => {
|
||||
expect(toolProvider.listTools).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('streams OpenAI-compatible reasoning deltas before the answer', async () => {
|
||||
const stream = [
|
||||
`data: ${JSON.stringify({
|
||||
choices: [
|
||||
{
|
||||
delta: {
|
||||
reasoning_content: '先分析'
|
||||
}
|
||||
}
|
||||
]
|
||||
})}`,
|
||||
'',
|
||||
`data: ${JSON.stringify({
|
||||
choices: [
|
||||
{
|
||||
delta: {
|
||||
reasoning_content: ',再验证'
|
||||
}
|
||||
}
|
||||
]
|
||||
})}`,
|
||||
'',
|
||||
`data: ${JSON.stringify({
|
||||
choices: [
|
||||
{
|
||||
delta: {
|
||||
content: '最终回答'
|
||||
}
|
||||
}
|
||||
]
|
||||
})}`,
|
||||
'',
|
||||
'data: [DONE]',
|
||||
'',
|
||||
''
|
||||
].join('\n')
|
||||
const runtime = new ModelAgentRuntime({
|
||||
apiKey: 'test-key',
|
||||
baseUrl: 'https://api.deepseek.com',
|
||||
model: 'deepseek-reasoner',
|
||||
protocol: 'openai-chat-completions',
|
||||
authentication: 'api-key',
|
||||
fetcher: vi.fn<typeof fetch>(async () =>
|
||||
new Response(stream, {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'text/event-stream' }
|
||||
})
|
||||
)
|
||||
})
|
||||
const events = []
|
||||
|
||||
for await (const event of runtime.run(
|
||||
{
|
||||
requestId: 'a431666e-5ec8-45e6-beb4-654132eed128',
|
||||
conversationId: 'conversation-deepseek-reasoning',
|
||||
prompt: '分析这个问题'
|
||||
},
|
||||
new AbortController().signal
|
||||
)) {
|
||||
events.push(event)
|
||||
}
|
||||
|
||||
expect(
|
||||
events.filter(
|
||||
(event) => event.type === 'reasoning' || event.type === 'text'
|
||||
)
|
||||
).toEqual([
|
||||
{
|
||||
requestId: 'a431666e-5ec8-45e6-beb4-654132eed128',
|
||||
type: 'reasoning',
|
||||
delta: '先分析'
|
||||
},
|
||||
{
|
||||
requestId: 'a431666e-5ec8-45e6-beb4-654132eed128',
|
||||
type: 'reasoning',
|
||||
delta: ',再验证'
|
||||
},
|
||||
{
|
||||
requestId: 'a431666e-5ec8-45e6-beb4-654132eed128',
|
||||
type: 'text',
|
||||
delta: '最终回答'
|
||||
}
|
||||
])
|
||||
expect(events.at(-1)).toMatchObject({ type: 'done' })
|
||||
})
|
||||
|
||||
it('keeps browser and workspace tools out of Ask mode', async () => {
|
||||
const fetcher = vi.fn<typeof fetch>(async () =>
|
||||
new Response('data: {"choices":[{"delta":{"content":"只读回答"}}]}\n\ndata: [DONE]\n\n', {
|
||||
|
||||
@@ -1399,6 +1399,11 @@ describe('App', () => {
|
||||
(_, element) => element?.textContent === rawToolOutput
|
||||
)
|
||||
).toBeVisible()
|
||||
const activeReasoning = screen.getAllByText('正在推理')
|
||||
expect(activeReasoning).toHaveLength(2)
|
||||
for (const reasoning of activeReasoning) {
|
||||
expect(reasoning.closest('details')).toHaveAttribute('open')
|
||||
}
|
||||
|
||||
act(() => {
|
||||
if (!request) {
|
||||
|
||||
@@ -5446,11 +5446,7 @@ function App(): React.JSX.Element {
|
||||
<details
|
||||
className="message-reasoning"
|
||||
key={item.block.id}
|
||||
open={
|
||||
message.state === 'streaming' &&
|
||||
message.blocks?.at(-1)?.id ===
|
||||
item.block.id
|
||||
}
|
||||
open={message.state === 'streaming'}
|
||||
>
|
||||
<summary>
|
||||
{message.state === 'streaming'
|
||||
|
||||
Reference in New Issue
Block a user